< Summary

Line coverage
37%
Covered lines: 3928
Uncovered lines: 6659
Coverable lines: 10587
Total lines: 15049
Line coverage: 37.1%
Branch coverage
34%
Covered branches: 2386
Total branches: 6918
Branch coverage: 34.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_AllowedToDependOnAllocationState()0%60%
File 1: get_Kind()0%40%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 1: .ctor(...)100%1100%
File 1: GetContext(...)100%1100%
File 1: VisitOneStatement(...)25%1230%
File 1: VisitTopLevelFrameExpression(...)100%10%
File 1: DesugarFunctionsInFrameClause(...)100%10%
File 1: FrameArrowToObjectSet(...)0%100%
File 1: VisitExpression(...)100%2100%
File 1: VisitOneExpression(...)8.33%368.88%
File 1: DiscoverBestBounds_MultipleVars(...)0%40%
File 1: DiscoverBestBounds_MultipleVars_AllowReordering(...)0%260%
File 1: DiscoverAllBounds_Aux_MultipleVars(...)0%40%
File 1: DiscoverAllBounds_SingleVar(...)100%10%
File 1: DiscoverAllBounds_Aux_SingleVar(...)0%1020%
File 1: DiscoverBoundsFunctionCallExpr(...)0%40%
File 1: NormalizedConjuncts()0%860%
File 1: SanitizeForBoundDiscovery(...)0%540%
File 1: IsMonotonic(...)0%120%
File 2: ResolveNamesAndInferTypes(...)100%4100%
File 2: ResolveNamesAndInferTypesForOneDeclarationInitial(...)62.5%857.57%
File 2: ResolveNamesAndInferTypesForOneDeclaration(...)50%1836.95%
File 2: EagerAddAssignableConstraint(...)100%4100%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: PrintTypeConstraintState(...)12.5%1623.52%
File 2: SolveAllTypeConstraints()20%1043.47%
File 2: ResolveAttributes(...)91.66%1283.33%
File 2: ResolveExpression(...)43.18%30845.51%
File 2: ResolveTypeParameters(...)80%1082.35%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainTypeExprBool(...)100%1100%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainAssignable(...)78.57%1490.47%
File 2: ConstrainAssignableTypeArgs(...)85.71%1478.37%
File 2: ConstrainSubtypeRelation_Equal(...)87.5%1677.77%
File 2: ConstrainSubtypeRelation(...)100%12100%
File 2: ConstrainSubtypeRelation_Aux(...)91.66%1291.66%
File 2: DetermineRootLeaf(...)87.03%5481.25%
File 2: .ctor(...)100%1100%
File 2: AssignProxyAndHandleItsConstraints(...)50%277.77%
File 2: AssignProxyAndHandleItsConstraints_aux(...)60.86%4653.12%
File 2: ImposeSubtypingConstraint(...)80%2086.66%
File 2: ConstrainTypeHead_Recursive(...)66.66%685.71%
File 2: ConstrainTypeHead(...)51.89%7963.23%
File 2: KeepConstraints(...)88.88%2783.33%
File 2: .ctor(...)100%1100%
File 2: ToString()0%40%
File 2: Confirm(...)61.52%51259.72%
File 2: ProxyWithNoSubTypeConstraint(...)70%1083.33%
File 2: CouldBeAnything()100%10%
File 2: FindCollectionType(...)72.22%1880.95%
File 2: .ctor(...)100%1100%
File 2: .ctor(...)100%1100%
File 2: PartiallySolveTypeConstraints(...)51.68%17850.34%
File 2: NewIntegerBasedProxy(...)100%1100%
File 2: ContainsAsTypeParameter(...)0%140%
File 2: AddAllProxies(...)100%4100%
File 2: ProcessAssignable(...)70.83%2459.37%
File 2: ConvertAssignableToSubtypeConstraints(...)100%14100%
File 2: TightenUpEquatable(...)90%10100%
File 2: ProcessOneSubtypingConstraintAndItsSubs(...)90%2096.15%
File 2: ProcessFullStrength_SubDirection(...)100%10100%
File 2: ProcessFullStrength_SuperDirection(...)100%10100%
File 2: AssignKnownEnd(...)46.42%2853.84%
File 2: AssignKnownEndsFullstrength(...)0%300%
File 2: AssignKnownEndsFullstrength_SubDirection(...)53.84%2665.78%
File 2: CloseOverAssignableRhss(...)0%140%
File 2: HasApplicableNullableRefTypeConstraint(...)0%60%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection(...)100%6100%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection_aux(...)20%1046.15%
File 2: AssignKnownEndsFullstrength_SuperDirection(...)93.33%3094.87%
File 2: Reaches(...)50%277.77%
File 2: Reaches_aux(...)72.22%1887.5%
File 2: ResolveClassMemberBodiesInitial(...)33.33%1242.1%
File 2: ResolveClassMemberBodies(...)63.63%2269.04%
File 2: ResolveCtorTypes(...)0%120%
File 2: ResolveCtorSignature(...)0%20%
File 2: AddDatatypeDependencyEdge(...)0%60%
File 2: ResolveFrameExpressionTopLevel(...)100%10%
File 2: ResolveFrameExpression(...)0%140%
File 2: ResolveIterator(...)0%240%
File 2: CheckIsLvalue(...)7.69%2619.35%
File 2: ResolveBlockStatement(...)37.5%847.05%
File 2: ResolveStatementWithLabels(...)12.5%825%
File 2: ResolveAlternatives(...)0%140%
File 2: ResolveCallStmt(...)50%3663.33%
File 2: ResolveActualParameters(...)40.32%6257.26%
File 2: GetLocationInformation(...)83.33%6100%
File 2: ResolveDotSuffix_Type(...)0%260%
File 2: CreateResolver_IdentifierExpr(...)75%1677.77%
File 2: ResolveStatement(...)17.73%28219.79%
File 2: ResolveLoopSpecificationComponents(...)0%120%
File 2: ResolveParameterDefaultValues(...)44.44%1841.66%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: .ctor(...)100%10%
File 2: ResolveTypeLenient(...)53.94%7647.74%
File 2: FillInTypeArguments(...)0%160%
File 2: TypeConstraintsIncludeProxy(...)100%1100%
File 2: TypeConstraintsIncludeProxy_Aux(...)22.22%1844%
File 2: ResolveTypeRhs(...)0%680%
File 2: ResolveMember(...)37.5%2436.95%
File 2: PartiallyResolveTypeForMemberSelection(...)51.02%9847.14%
File 2: GetBaseTypeFromProxy(...)100%1895.45%
File 2: GetBaseTypeFromProxy_Eq(...)100%2100%
File 2: GetBaseTypeFromProxy_EqAux(...)31.25%1639.13%
File 2: GetRelatedTypeProxies(...)84.37%3280%
File 2: JoinOfAllSubtypes(...)52.77%3670.27%
File 2: MeetOfAllSupertypes(...)96.87%3295.55%
File 2: CheckVariance(...)42.1%3854.9%
File 2: ConstrainToIntegerType(...)100%2100%
File 2: ResolveDatatypeUpdate(...)0%220%
File 2: DesugarDatatypeUpdate(...)0%160%
File 2: ResolveNameSegment(...)100%1100%
File 2: ResolveNameSegment(...)15.62%6426.8%
File 2: ResolveDatatypeConstructor(...)0%140%
File 2: ResolveNameSegment_Type(...)71.42%1477.41%
File 2: ResolveDotSuffix(...)20.73%8229.6%
File 2: CheckForAmbiguityInShadowedImportedModule(...)50%433.33%
File 2: NameConflictsWithModuleContents(...)0%100%
File 2: ResolveExprDotCall(...)58.33%4861.76%
File 2: ResolveApplySuffix(...)59.67%6268.31%
File 2: ResolveDatatypeValue(...)43.75%1670%
File 2: ResolveFunctionCallExpr(...)0%300%
File 2: ResolveReceiver(...)0%40%
File 2: ResolveSeqSelectExpr(...)87.5%896.77%
File 3: get_Options()100%1100%
File 3: .ctor(...)100%176.92%
File 3: get_Reporter()100%1100%
File 3: get_TypeConstraintErrorsToBeReported()100%1100%
File 3: RevealedInScope(...)0%20%
File 3: VisibleInScope(...)100%2100%
File 3: FreshTempVarName(...)0%20%
File 3: Create(...)0%100%
File 3: Name(...)0%40%
File 3: ModuleNames(...)0%40%
File 3: Create(...)0%20%
File 3: Equals(...)0%40%
File 3: GetHashCode(...)0%20%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: Create(...)0%20%
File 3: Equals(...)100%10%
File 3: GetHashCode(...)100%10%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: .ctor(...)100%4100%
File 3: AddRotateMember(...)100%1100%
File 3: ObjectInvariant()100%10%
File 3: AsValuetypeDecl(...)0%40%
File 3: CheckDupModuleNames(...)62.5%876.47%
File 3: ResolveProgram(...)72.29%14878.54%
File 3: ResolveValuetypeDecls()87.5%878.57%
File 3: ResolveModuleDefinition(...)29.16%2456.25%
File 3: ResolveModuleExport(...)10.89%15614.54%
File 3: CheckModuleExportConsistency(...)3.57%2810%
File 3: .ctor(...)100%1100%
File 3: BindName(...)50%287.5%
File 3: TryLookup(...)100%10%
File 3: TryLookupFilter(...)0%60%
File 3: get_ModuleList()100%10%
File 3: SubBindings(...)100%10%
File 3: BindModuleNames(...)28.12%3224.56%
File 3: ShortenPrefix(...)100%10%
File 3: BindModuleName_LiteralModuleDecl(...)0%80%
File 3: ResolveQualifiedModuleIdRootRefines(...)100%10%
File 3: ResolveQualifiedModuleIdRootImport(...)0%60%
File 3: ResolveQualifiedModuleIdRootAbstract(...)0%60%
File 3: ProcessDependenciesDefinition(...)20%2024.13%
File 3: ProcessDependencies(...)20%1030%
File 3: ModuleNotFoundErrorMessage(...)0%20%
File 3: EquivIfPresent(...)50%280%
File 3: MergeSignature(...)55%2057.14%
File 3: ResolveOpenedImports(...)50%1644.44%
File 3: ResolveAlias(...)0%20%
File 3: ResolveOpenedImportsWorker(...)0%360%
File 3: RegisterTopLevelDecls(...)68.88%9074.68%
File 3: RegisterMembers(...)26.47%3414.49%
File 3: RegisterByMethod(...)0%40%
File 3: MakeAbstractSignature(...)0%100%
File 3: CloneDeclaration(...)0%20%
File 3: ResolveModuleQualifiedId(...)0%120%
File 3: ResolveExport(...)0%180%
File 3: RevealAllInScope(...)100%12100%
File 3: ResolveTopLevelDecls_Signatures(...)55.76%5257.14%
File 3: .cctor()100%10%
File 3: ResolveTopLevelDecls_Core(...)45.93%39445.54%
File 3: FillInPostConditionsAndBodiesOfPrefixLemmas(...)2.94%342.5%
File 3: CheckIsOkayWithoutRHS(...)0%120%
File 3: ResolveClassMembers_Pass1(...)71.87%3271.42%
File 3: CheckForUnnecessaryEqualitySupportDeclarations(...)25%437.5%
File 3: CheckParameterDefaultValuesAreCompilable(...)12.5%837.5%
File 3: ReportCallGraphCycleError(...)100%10%
File 3: ReportCycleError(...)100%10%
File 3: MaxBV(...)100%10%
File 3: MaxBV(...)100%10%
File 3: FigureOutNativeType(...)0%4670%
File 3: CheckOlderParameters(...)90%1077.77%
File 3: CheckExpression(...)100%1100%
File 3: CheckExpression(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneExpr(...)50%853.84%
File 3: VisitOneStmt(...)41.66%1245.45%
File 3: CheckForFuelAdjustments(...)3.57%2814.81%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)100%1100%
File 3: Invert(...)0%40%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%520%
File 3: KNatMismatchError(...)0%60%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%180%
File 3: VisitOneStmt(...)0%40%
File 3: ExtremePredicateChecks(...)100%10%
File 3: .ctor(...)100%10%
File 3: VisitOneStmt(...)0%80%
File 3: VisitOneExpr(...)0%40%
File 3: ExtremeLemmaChecks(...)100%10%
File 3: ExtremeLemmaChecks(...)0%20%
File 3: CheckTypeCharacteristics_Stmt(...)100%1100%
File 3: CheckTypeCharacteristics_Expr(...)100%1100%
File 3: CheckTypeCharacteristics_Type(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)42.85%5635.55%
File 3: VisitOneExpr(...)70.27%7469.41%
File 3: VisitType(...)46.66%3066.66%
File 3: CheckTypeInstantiation(...)50%672.72%
File 3: CheckCharacteristics(...)46.66%3042.3%
File 3: TypeEqualityErrorMessageHint(...)0%60%
File 3: CanCompareWith(...)6.25%1620%
File 3: ComputeGhostInterest(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)50%444.44%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)10%1015%
File 3: .ctor(...)100%1100%
File 3: CheckInit(...)100%10%
File 3: CheckInit(...)0%80%
File 3: VisitExpr(...)100%10%
File 3: VisitOneExpr(...)0%100%
File 3: LiberalRHSVisit(...)0%240%
File 3: IsThisDotField(...)0%20%
File 3: IsCollectionOperator(...)0%100%
File 3: InferRequiredEqualitySupport(...)43.75%3266.66%
File 3: ResolveParentTraitTypes(...)4.54%2229.62%
File 3: RegisterInheritedMembers(...)12.5%4815.94%
File 3: ResolveClassMemberTypes(...)50%2450.98%
File 3: InheritedTraitMembers(...)7.89%7610%
File 3: CheckOverride_FunctionParameters(...)0%120%
File 3: CheckOverride_MethodParameters(...)0%100%
File 3: CheckOverride_TypeParameters(...)0%160%
File 3: CheckOverride_ResolvedParameters(...)0%300%
File 3: SccStratosphereCheck(...)0%140%
File 3: ComputeGroundingCtor(...)0%180%
File 3: CheckCanBeConstructed(...)0%360%
File 3: DetermineEqualitySupport(...)0%620%
File 3: IsRecognizedAttribute(...)0%500%
File 3: ScopePushAndReport(...)100%1100%
File 3: ScopePushAndReport(...)50%455.55%
File 3: ResolveFunctionSignature(...)75%877.77%
File 3: DisallowNonGhostFieldSpecifiers(...)0%40%
File 3: ResolveMethodSignature(...)75%887.5%
File 3: ResolveIteratorSignature(...)0%160%
File 3: ObjectInvariant()100%10%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: ResolvedArrayType(...)100%10%
File 3: FillInDefaultLoopDecreases(...)0%1070%
File 3: VarDotMethod(...)100%10%
File 3: makeTemp(...)100%10%
File 3: EnsureSupportsErrorHandling(...)0%200%
File 3: CheckLocalityUpdates(...)0%260%
File 3: CheckLocalityUpdatesLhs(...)0%40%
File 3: .ctor(...)100%10%
File 3: ToString()0%20%
File 3: FindAllMembers(...)0%20%
File 3: GetThisType(...)50%466.66%
File 3: GetReceiverType(...)100%10%
File 3: ResolveDominatingLabelInExpr(...)0%60%
File 3: VarDotFunction(...)100%10%
File 3: LetPatIn(...)100%10%
File 3: LetVarIn(...)100%10%
File 3: ResolveLetOrFailExpr(...)0%20%
File 3: SelectAppropriateArrowTypeForFunction(...)100%1100%
File 3: SelectAppropriateArrowType(...)50%480%
File 3: ConstrainToIntegerType(...)100%1100%
File 3: ResolveNestedMatchExpr(...)100%10%
File 3: ResolveCasePattern(...)22%5026.58%
File 3: FillInDefaultValueExpressions()50%271.42%
File 3: FillInDefaultValueExpression(...)0%40%
File 3: .ctor(...)100%10%
File 3: Substitute(...)0%20%
File 3: BuildTypeArgumentSubstitute(...)62.5%873.33%
File 3: AddParentTypeParameterSubstitutions(...)60%1075%
File 3: GhostPrefix(...)50%2100%
File 3: GetSignatureExt(...)0%40%
File 3: GetSignature(...)100%10%
File 3: GetImpliedTypeConstraint(...)100%1100%
File 3: GetImpliedTypeConstraint(...)50%860%
File 3: FreeVariables(...)0%340%
File 3: .cctor()100%1100%
File 3: get_Msg()0%80%
File 3: .ctor(...)100%1100%
File 3: ResolveOp(...)80%10582.78%
File 3: CollectFriendlyCallsInExtremeLemmaSpecification(...)0%20%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%280%
File 4: get_IsPrefixPredicate()100%1100%
File 4: get_IsExtremePredicate()100%1100%
File 4: get_IsPrefixDeclaration()50%2100%
File 4: .ctor(...)100%1100%
File 4: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 4: get_reporter()100%10%
File 4: .ctor(...)100%1100%
File 4: GetContext(...)100%1100%
File 4: VisitOneDeclaration(...)25%2023.33%
File 4: VisitField(...)50%257.14%
File 4: VisitOneStatement(...)50%244.44%
File 4: PostVisitOneStatement(...)58.33%1252.17%
File 4: PostVisitOneExpression(...)47.97%17346.69%
File 4: VisitExtendedPattern(...)0%40%
File 4: IsDetermined(...)100%2100%
File 4: CheckTypeIsDetermined(...)25%445.45%
File 4: CheckTypeArgsContainNoOrdinal(...)50%2100%
File 4: CheckContainsNoOrdinal(...)50%271.42%

File(s)

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/BoundsDiscovery.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright by the contributors to the Dafny Project
 4// SPDX-License-Identifier: MIT
 5//
 6//-----------------------------------------------------------------------------
 7using System.Collections.Generic;
 8using System.Linq;
 9using System.Diagnostics.Contracts;
 10using Microsoft.Boogie;
 11
 12namespace Microsoft.Dafny {
 13  public partial class Resolver {
 14    private class BoundsDiscoveryVisitor : ASTVisitor<BoundsDiscoveryVisitor.BoundsDiscoveryContext> {
 15      public class BoundsDiscoveryContext : IASTVisitorContext {
 16        private readonly IASTVisitorContext astVisitorContext;
 17        readonly bool inLambdaExpression;
 18
 19        public bool AllowedToDependOnAllocationState =>
 020          !(astVisitorContext is Function or ConstantField or RedirectingTypeDecl || inLambdaExpression);
 21
 22        public string Kind {
 023          get {
 24            // assumes context denotes a lambda expression, redirecting type, or member declaration
 025            if (inLambdaExpression) {
 026              return "lambda expression";
 27            }
 28            string kind;
 029            if (astVisitorContext is RedirectingTypeDecl redirectingTypeDecl) {
 030              kind = redirectingTypeDecl.WhatKind;
 031            } else {
 032              var memberDecl = (MemberDecl)astVisitorContext;
 033              kind = memberDecl.WhatKind;
 034            }
 035            return $"{kind} definition";
 036          }
 37        }
 38
 4215039        public BoundsDiscoveryContext(IASTVisitorContext astVisitorContext) {
 2107540          this.astVisitorContext = astVisitorContext;
 2107541          this.inLambdaExpression = false;
 2107542        }
 43
 44        /// <summary>
 45        /// This constructor is used to say that, within parentContext, the context is inside a lambda
 46        /// expression.
 47        /// </summary>
 958048        public BoundsDiscoveryContext(BoundsDiscoveryContext parentContext, LambdaExpr lambdaExpr) {
 479049          this.astVisitorContext = parentContext.astVisitorContext;
 479050          this.inLambdaExpression = true;
 479051        }
 52
 850053        ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 54      }
 55
 56      private readonly ErrorReporter reporter;
 57
 267058      public BoundsDiscoveryVisitor(ErrorReporter reporter) {
 133559        this.reporter = reporter;
 133560      }
 61
 2107562      public override BoundsDiscoveryContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostconditi
 2107563        return new BoundsDiscoveryContext(astVisitorContext);
 2107564      }
 65
 119732066      protected override bool VisitOneStatement(Statement stmt, BoundsDiscoveryContext context) {
 119732067        if (stmt is ForallStmt forallStmt) {
 068          forallStmt.Bounds = DiscoverBestBounds_MultipleVars(forallStmt.BoundVars, forallStmt.Range, true);
 069          if (forallStmt.Body == null) {
 070            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, forallStmt.Tok, "note, this forall statement 
 071          }
 119732072        } else if (stmt is AssignSuchThatStmt assignSuchThatStmt) {
 073          if (assignSuchThatStmt.AssumeToken == null) {
 074            var varLhss = new List<IVariable>();
 075            foreach (var lhs in assignSuchThatStmt.Lhss) {
 076              var ide = (IdentifierExpr)lhs.Resolved;  // successful resolution implies all LHS's are IdentifierExpr's
 077              varLhss.Add(ide.Var);
 078            }
 079            assignSuchThatStmt.Bounds = DiscoverBestBounds_MultipleVars(varLhss, assignSuchThatStmt.Expr, true);
 080          }
 119732081        } else if (stmt is OneBodyLoopStmt oneBodyLoopStmt) {
 082          oneBodyLoopStmt.ComputeBodySurrogate(reporter);
 083        }
 84
 119732085        return base.VisitOneStatement(stmt, context);
 119732086      }
 87
 088      public override void VisitTopLevelFrameExpression(FrameExpression frameExpression, BoundsDiscoveryContext context)
 089        DesugarFunctionsInFrameClause(frameExpression);
 090        base.VisitTopLevelFrameExpression(frameExpression, context);
 091      }
 92
 093      void DesugarFunctionsInFrameClause(FrameExpression frameExpression) {
 094        frameExpression.DesugaredExpression = FrameArrowToObjectSet(frameExpression.E);
 095      }
 96
 97      /// <summary>
 98      /// The motivation for this method is to convert a reads-clause frame expression "f.reads" into a set.
 99      /// More generally, if the given expression "e" has type "X ~> collection<Y>", for some list of type X,
 100      /// some reference type Y, and "collection" being "set", "iset", "seq", or "multiset", then this method
 101      /// returns an expression of type "set<Y>" denoting
 102      ///
 103      ///     UNION x: X :: e(x)                      // e.g., UNION x: X :: f.reads(x)
 104      ///
 105      /// For example, if "e" is an expression "f.reads" of type "X ~> set<object>", then the expression
 106      /// returned is the union of "f.reads(x)" over all inputs "x" to "f".
 107      ///
 108      /// If the type of "e" is not of the form "X ~> collection<Y>" as stated above, then this method simply
 109      /// returns the given "e".
 110      ///
 111      /// Dafny does not have a UNION comprehension, so the expression returned has the form
 112      ///
 113      ///     { obj: Y | exists x: X :: obj in e(x) }
 114      ///
 115      /// which in Dafny notation is written
 116      ///
 117      ///     set x: X, obj: Y | obj in e(x) :: obj
 118      ///
 119      /// Note, since Y is a reference type and there is, at any one time, only a finite number of references,
 120      /// the result type is finite.
 121      ///
 122      /// Note: A pending improvement would be to limit the range of the set comprehension to the values for x
 123      /// that satisfy e's precondition.
 124      /// </summary>
 0125      public static Expression FrameArrowToObjectSet(Expression e) {
 126        Contract.Requires(e != null);
 0127        var arrowType = e.Type.AsArrowType;
 0128        if (arrowType == null) {
 0129          return e;
 130        }
 0131        var collectionType = arrowType.Result.AsCollectionType;
 0132        if (collectionType == null || collectionType.NormalizeExpand() is MapType) {
 0133          return e;
 134        }
 0135        var elementType = collectionType.Arg; // "elementType" is called "Y" in the description of this method, above
 0136        if (!elementType.IsRefType) {
 0137          return e;
 138        }
 139
 0140        var boundVarDecls = new List<BoundVar>();
 0141        var boundVarUses = new List<Expression>();
 0142        var i = 0;
 0143        foreach (var functionArgumentType in arrowType.Args) {
 0144          var bv = new BoundVar(e.tok, $"_x{i}", functionArgumentType);
 0145          boundVarDecls.Add(bv);
 0146          boundVarUses.Add(new IdentifierExpr(e.tok, bv.Name) { Type = bv.Type, Var = bv });
 0147          i++;
 0148        }
 0149        var objVar = new BoundVar(e.tok, "_obj", elementType);
 0150        var objUse = new IdentifierExpr(e.tok, objVar.Name) { Type = objVar.Type, Var = objVar };
 0151        boundVarDecls.Add(objVar);
 152
 0153        var collection = new ApplyExpr(e.tok, e, boundVarUses, e.tok) {
 0154          Type = collectionType
 0155        };
 0156        var resolvedOpcode = collectionType.ResolvedOpcodeForIn;
 157
 0158        var inCollection = new BinaryExpr(e.tok, BinaryExpr.Opcode.In, objUse, collection) {
 0159          ResolvedOp = resolvedOpcode,
 0160          Type = Type.Bool
 0161        };
 162
 0163        var attributes = new Attributes("_reads", new List<Expression>(), null);
 0164        return new SetComprehension(e.tok, e.RangeToken, true, boundVarDecls, inCollection, objUse, attributes) {
 0165          Type = new SetType(true, elementType)
 0166        };
 0167      }
 168
 2767430169      protected override void VisitExpression(Expression expr, BoundsDiscoveryContext context) {
 2772220170        if (expr is LambdaExpr lambdaExpr) {
 4790171          lambdaExpr.Reads.Iter(DesugarFunctionsInFrameClause);
 172
 173          // Make the context more specific when visiting inside a lambda expression
 4790174          context = new BoundsDiscoveryContext(context, lambdaExpr);
 4790175        }
 2767430176        base.VisitExpression(expr, context);
 2767430177      }
 178
 2767430179      protected override bool VisitOneExpression(Expression expr, BoundsDiscoveryContext context) {
 2767430180        if (expr is ComprehensionExpr and not LambdaExpr) {
 0181          var e = (ComprehensionExpr)expr;
 182          // apply bounds discovery to quantifiers, finite sets, and finite maps
 0183          Expression whereToLookForBounds = null;
 0184          var polarity = true;
 0185          if (e is QuantifierExpr quantifierExpr) {
 0186            whereToLookForBounds = quantifierExpr.LogicalBody();
 0187            polarity = quantifierExpr is ExistsExpr;
 0188          } else if (e is SetComprehension setComprehension) {
 0189            whereToLookForBounds = setComprehension.Range;
 0190          } else if (e is MapComprehension) {
 0191            whereToLookForBounds = e.Range;
 0192          } else {
 0193            Contract.Assert(false);  // otherwise, unexpected ComprehensionExpr
 0194          }
 0195          if (whereToLookForBounds != null) {
 0196            e.Bounds = DiscoverBestBounds_MultipleVars_AllowReordering(e.BoundVars, whereToLookForBounds, polarity);
 0197            if (2 <= reporter.Options.Allocated && !context.AllowedToDependOnAllocationState) {
 0198              foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds,
 0199                         ComprehensionExpr.BoundedPool.PoolVirtues.IndependentOfAlloc)) {
 0200                var how = Attributes.Contains(e.Attributes, "_reads") ? "(implicitly by using a function in a reads clau
 0201                var message =
 0202                  $"a {e.WhatKind} involved in a {context.Kind} {how}is not allowed to depend on the set of allocated re
 0203                  $" but values of '{bv.Name}' (of type '{bv.Type}') may contain references";
 0204                if (bv.Type.IsTypeParameter || bv.Type.IsAbstractType) {
 0205                  message += $" (perhaps declare its type as '{bv.Type}(!new)')";
 0206                }
 0207                message += " (see documentation for 'older' parameters)";
 0208                reporter.Error(MessageSource.Resolver, e, message);
 0209              }
 0210            }
 211
 0212            if ((e as SetComprehension)?.Finite == true || (e as MapComprehension)?.Finite == true) {
 213              // the comprehension had better produce a finite set
 0214              if (e.Type.HasFinitePossibleValues) {
 215                // This means the set is finite, regardless of if the Range is bounded.  So, we don't give any error her
 216                // However, if this expression is used in a non-ghost context (which is not yet known at this stage of
 217                // resolution), the resolver will generate an error about that later.
 0218              } else {
 219                // we cannot be sure that the set/map really is finite
 0220                foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds, ComprehensionExpr.
 0221                  reporter.Error(MessageSource.Resolver, e,
 0222                    "the result of a {0} must be finite, but Dafny's heuristics can't figure out how to produce a bounde
 0223                    e.WhatKind, bv.Name);
 0224                }
 0225              }
 0226            }
 0227          }
 228
 0229        }
 230
 2767430231        return base.VisitOneExpression(expr, context);
 2767430232      }
 233    }
 234
 235    /// <summary>
 236    /// For a list of variables "bvars", returns a list of best bounds for each respective variable.
 237    /// If no bound is found for a variable "v", then the bound for "v" in the returned list is set to "null".
 238    /// </summary>
 239    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars<VT>(List<VT> bvars, Expression exp
 0240      bool polarity) where VT : IVariable {
 241      Contract.Requires(bvars != null);
 242      Contract.Requires(expr != null);
 243      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0244      foreach (var bv in bvars) {
 0245        var c = GetImpliedTypeConstraint(bv, bv.Type);
 0246        expr = polarity ? Expression.CreateAnd(c, expr) : Expression.CreateImplies(c, expr);
 0247      }
 0248      var bests = DiscoverAllBounds_Aux_MultipleVars(bvars, expr, polarity);
 0249      return bests;
 0250    }
 251
 252    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars_AllowReordering<VT>(List<VT> bvars
 0253      bool polarity) where VT : IVariable {
 254      Contract.Requires(bvars != null);
 255      Contract.Requires(expr != null);
 256      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0257      var bounds = DiscoverBestBounds_MultipleVars(bvars, expr, polarity);
 0258      if (bvars.Count > 1) {
 259        // It may be helpful to try all permutations (or, better yet, to use an algorithm that keeps track of the depend
 260        // and discovers good bounds more efficiently). However, all permutations would be expensive. Therefore, we try 
 261        // other permutation, namely the reversal "bvars". This covers the important case where there are two bound vari
 262        // that work out in the opposite order. It also covers one more case for the (probably rare) case of there being
 263        // than two bound variables.
 0264        var bvarsMissyElliott = new List<VT>(bvars);  // make a copy
 0265        bvarsMissyElliott.Reverse();  // and then flip it and reverse it, Ti esrever dna ti pilf nwod gnaht ym tup I
 0266        var boundsMissyElliott = DiscoverBestBounds_MultipleVars(bvarsMissyElliott, expr, polarity);
 267        // Figure out which one seems best
 0268        var meBetter = 0;
 0269        for (int i = 0; i < bvars.Count; i++) {
 0270          var orig = bounds[i];
 0271          var me = boundsMissyElliott[i];
 0272          if (orig == null && me != null) {
 0273            meBetter = 1; break; // end game
 0274          } else if (orig != null && me == null) {
 0275            meBetter = -1; break; // end game
 0276          } else if (orig != null && me != null) {
 0277            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter--; }
 0278            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter--; }
 0279            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter++; }
 0280            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter++; }
 0281          }
 0282        }
 0283        if (meBetter > 0) {
 284          // yes, this reordering seems to have been better
 0285          bvars.Reverse();
 0286          return boundsMissyElliott;
 287        }
 0288      }
 0289      return bounds;
 0290    }
 291
 292    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_MultipleVars<VT>(List<VT> bvars, Expression
 0293      bool polarity) where VT : IVariable {
 294      Contract.Requires(bvars != null);
 295      Contract.Requires(expr != null);
 296      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 297      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>().Count == bvars.Count);
 0298      var knownBounds = new List<ComprehensionExpr.BoundedPool>();
 0299      for (var j = 0; j < bvars.Count; j++) {
 0300        knownBounds.Add(null);
 0301      }
 302      // Note, in the following loop, it's important to go backwards, because DiscoverAllBounds_Aux_SingleVar assumes "k
 303      // filled in for higher-indexed variables.
 0304      for (var j = bvars.Count; 0 <= --j;) {
 0305        var bounds = DiscoverAllBounds_Aux_SingleVar(bvars, j, expr, polarity, knownBounds);
 0306        knownBounds[j] = ComprehensionExpr.BoundedPool.GetBest(bounds);
 307#if DEBUG_PRINT
 308        if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 309          var ib = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 310          var lo = ib.LowerBound == null ? "" : Printer.ExprToString(ib.LowerBound);
 311          var hi = ib.UpperBound == null ? "" : Printer.ExprToString(ib.UpperBound);
 312          Console.WriteLine("DEBUG: Bound for var {3}, {0}:  {1} .. {2}", bvars[j].Name, lo, hi, j);
 313        } else if (knownBounds[j] is ComprehensionExpr.SetBoundedPool) {
 314          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  in {1}", bvars[j].Name, Printer.ExprToString(((Comprehensio
 315        } else {
 316          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  {1}", bvars[j].Name, knownBounds[j], j);
 317        }
 318#endif
 0319      }
 0320      return knownBounds;
 0321    }
 322
 0323    public static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_SingleVar<VT>(VT v, Expression expr) where VT : 
 0324      expr = Expression.CreateAnd(GetImpliedTypeConstraint(v, v.Type), expr);
 0325      return DiscoverAllBounds_Aux_SingleVar(new List<VT> { v }, 0, expr, true, new List<ComprehensionExpr.BoundedPool>(
 0326    }
 327
 328    /// <summary>
 329    /// Returns a list of (possibly partial) bounds for "bvars[j]", each of which can be written without mentioning any 
 330    /// that is not bounded.
 331    /// </summary>
 332    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_SingleVar<VT>(List<VT> bvars, int j, Expres
 0333      bool polarity, List<ComprehensionExpr.BoundedPool> knownBounds) where VT : IVariable {
 334      Contract.Requires(bvars != null);
 335      Contract.Requires(0 <= j && j < bvars.Count);
 336      Contract.Requires(expr != null);
 337      Contract.Requires(knownBounds != null);
 338      Contract.Requires(knownBounds.Count == bvars.Count);
 0339      var bv = bvars[j];
 0340      var bounds = new List<ComprehensionExpr.BoundedPool>();
 341
 342      // Maybe the type itself gives a bound
 0343      if (bv.Type.IsBoolType) {
 0344        bounds.Add(new ComprehensionExpr.BoolBoundedPool());
 0345      } else if (bv.Type.IsCharType) {
 0346        bounds.Add(new ComprehensionExpr.CharBoundedPool());
 0347      } else if (bv.Type.IsDatatype && bv.Type.AsDatatype.HasFinitePossibleValues) {
 0348        bounds.Add(new ComprehensionExpr.DatatypeBoundedPool(bv.Type.AsDatatype));
 0349      } else if (bv.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0350        bounds.Add(new AssignSuchThatStmt.WiggleWaggleBound());
 0351      } else if (!bv.Type.MayInvolveReferences) {
 0352        bounds.Add(new ComprehensionExpr.AllocFreeBoundedPool(bv.Type));
 0353      }
 354
 355      // Go through the conjuncts of the range expression to look for bounds.
 0356      foreach (var conjunct in NormalizedConjuncts(expr, polarity)) {
 0357        if (conjunct is IdentifierExpr) {
 0358          var ide = (IdentifierExpr)conjunct;
 0359          if (ide.Var == (IVariable)bv) {
 0360            Contract.Assert(bv.Type.IsBoolType);
 0361            bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, true)));
 0362          }
 0363          continue;
 364        }
 0365        if (conjunct is UnaryOpExpr || conjunct is OldExpr) {
 366          // we also consider a unary expression sitting immediately inside an old
 0367          var unary = conjunct as UnaryOpExpr ?? ((OldExpr)conjunct).E.Resolved as UnaryOpExpr;
 0368          if (unary != null) {
 0369            var ide = unary.E.Resolved as IdentifierExpr;
 0370            if (ide != null && ide.Var == (IVariable)bv) {
 0371              if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot) {
 0372                bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, false)));
 0373              } else if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.Allocated) {
 0374                bounds.Add(new ComprehensionExpr.ExplicitAllocatedBoundedPool());
 0375              }
 0376            }
 0377          }
 0378          continue;
 379        }
 0380        if (conjunct is FunctionCallExpr functionCallExpr) {
 0381          DiscoverBoundsFunctionCallExpr(functionCallExpr, bv, bounds);
 0382          continue;
 383        }
 0384        var c = conjunct as BinaryExpr;
 0385        if (c == null) {
 386          // other than what we already covered above, we only know what to do with binary expressions
 0387          continue;
 388        }
 0389        var e0 = c.E0;
 0390        var e1 = c.E1;
 0391        int whereIsBv = SanitizeForBoundDiscovery(bvars, j, c.ResolvedOp, knownBounds, ref e0, ref e1);
 0392        if (whereIsBv < 0) {
 0393          continue;
 394        }
 0395        switch (c.ResolvedOp) {
 396          case BinaryExpr.ResolvedOpcode.InSet:
 0397            if (whereIsBv == 0) {
 0398              bounds.Add(new ComprehensionExpr.SetBoundedPool(e1, e0.Type, e1.Type.AsSetType.Arg, e1.Type.AsSetType.Fini
 0399            }
 0400            break;
 401          case BinaryExpr.ResolvedOpcode.Subset:
 0402            if (whereIsBv == 0) {
 0403              bounds.Add(new ComprehensionExpr.SubSetBoundedPool(e1, e1.Type.AsSetType.Finite));
 0404            } else {
 0405              bounds.Add(new ComprehensionExpr.SuperSetBoundedPool(e0));
 0406            }
 0407            break;
 408          case BinaryExpr.ResolvedOpcode.InMultiSet:
 0409            if (whereIsBv == 0) {
 0410              bounds.Add(new ComprehensionExpr.MultiSetBoundedPool(e1, e0.Type, e1.Type.AsMultiSetType.Arg));
 0411            }
 0412            break;
 413          case BinaryExpr.ResolvedOpcode.InSeq:
 0414            if (whereIsBv == 0 && e1.Type.AsSeqType is { } seqType) {
 0415              bounds.Add(new ComprehensionExpr.SeqBoundedPool(e1, e0.Type, seqType.Arg));
 0416            }
 0417            break;
 418          case BinaryExpr.ResolvedOpcode.InMap:
 0419            if (whereIsBv == 0) {
 0420              bounds.Add(new ComprehensionExpr.MapBoundedPool(e1, e0.Type, e1.Type.AsMapType.Arg, e1.Type.AsMapType.Fini
 0421            }
 0422            break;
 423          case BinaryExpr.ResolvedOpcode.EqCommon:
 424          case BinaryExpr.ResolvedOpcode.SetEq:
 425          case BinaryExpr.ResolvedOpcode.SeqEq:
 426          case BinaryExpr.ResolvedOpcode.MultiSetEq:
 427          case BinaryExpr.ResolvedOpcode.MapEq:
 0428            var otherOperand = whereIsBv == 0 ? e1 : e0;
 0429            bounds.Add(new ComprehensionExpr.ExactBoundedPool(otherOperand));
 0430            break;
 431          case BinaryExpr.ResolvedOpcode.Gt:
 432          case BinaryExpr.ResolvedOpcode.Ge:
 0433            Contract.Assert(false);
 0434            throw new cce.UnreachableException(); // promised by postconditions of NormalizedConjunct
 435          case BinaryExpr.ResolvedOpcode.Lt:
 0436            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0437              if (whereIsBv == 0) {
 438                // bv < E
 0439                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, e1));
 0440              } else {
 441                // E < bv
 0442                bounds.Add(new ComprehensionExpr.IntBoundedPool(Expression.CreateIncrement(e0, 1), null));
 0443              }
 0444            }
 0445            break;
 446          case BinaryExpr.ResolvedOpcode.Le:
 0447            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0448              if (whereIsBv == 0) {
 449                // bv <= E
 0450                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, Expression.CreateIncrement(e1, 1)));
 0451              } else {
 452                // E <= bv
 0453                bounds.Add(new ComprehensionExpr.IntBoundedPool(e0, null));
 0454              }
 0455            }
 0456            break;
 457          case BinaryExpr.ResolvedOpcode.RankLt:
 0458            if (whereIsBv == 0) {
 0459              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e0.Type.IsIndDatatype));
 0460            }
 0461            break;
 462          case BinaryExpr.ResolvedOpcode.RankGt:
 0463            if (whereIsBv == 1) {
 0464              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e1.Type.IsIndDatatype));
 0465            }
 0466            break;
 467          default:
 0468            break;
 469        }
 0470      }
 0471      return bounds;
 0472    }
 473
 474    private static void DiscoverBoundsFunctionCallExpr<VT>(FunctionCallExpr fce, VT boundVariable, List<ComprehensionExp
 0475      where VT : IVariable {
 476      Contract.Requires(fce != null);
 477      Contract.Requires(boundVariable != null);
 478      Contract.Requires(bounds != null);
 479
 0480      var formals = fce.Function.Formals;
 0481      Contract.Assert(formals.Count == fce.Args.Count);
 0482      if (LinqExtender.Zip(formals, fce.Args).Any(t => t.Item1.IsOlder && t.Item2.Resolved is IdentifierExpr ide && ide.
 0483        bounds.Add(new ComprehensionExpr.OlderBoundedPool());
 0484        return;
 485      }
 0486    }
 487
 488    /// <summary>
 489    /// Returns all conjuncts of "expr" in "polarity" positions.  That is, if "polarity" is "true", then
 490    /// returns the conjuncts of "expr" in positive positions; else, returns the conjuncts of "expr" in
 491    /// negative positions.  The method considers a canonical-like form of the expression that pushes
 492    /// negations inwards far enough that one can determine what the result is going to be (so, almost
 493    /// a negation normal form).
 494    /// As a convenience, arithmetic inequalities are rewritten so that the negation of an arithmetic
 495    /// inequality is never returned and the comparisons > and >= are never returned; the negation of
 496    /// a common equality or disequality is rewritten analogously.
 497    /// Requires "expr" to be successfully resolved.
 498    /// Ensures that what is returned is not a ConcreteSyntaxExpression.
 499    /// </summary>
 0500    static IEnumerable<Expression> NormalizedConjuncts(Expression expr, bool polarity) {
 501      // We consider 5 cases.  To describe them, define P(e)=Conjuncts(e,true) and N(e)=Conjuncts(e,false).
 502      //   *  X ==> Y    is treated as a shorthand for !X || Y, and so is described by the remaining cases
 503      //   *  X && Y     P(_) = P(X),P(Y)    and    N(_) = !(X && Y)
 504      //   *  X || Y     P(_) = (X || Y)     and    N(_) = N(X),N(Y)
 505      //   *  !X         P(_) = N(X)         and    N(_) = P(X)
 506      //   *  else       P(_) = else         and    N(_) = !else
 507      // So for ==>, we have:
 508      //   *  X ==> Y    P(_) = P(!X || Y) = (!X || Y) = (X ==> Y)
 509      //                 N(_) = N(!X || Y) = N(!X),N(Y) = P(X),N(Y)
 0510      expr = expr.Resolved;
 511
 512      // Binary expressions
 0513      var b = expr as BinaryExpr;
 0514      if (b != null) {
 0515        bool breakDownFurther = false;
 0516        bool p0 = polarity;
 0517        switch (b.ResolvedOp) {
 518          case BinaryExpr.ResolvedOpcode.And:
 0519            breakDownFurther = polarity;
 0520            break;
 521          case BinaryExpr.ResolvedOpcode.Or:
 0522            breakDownFurther = !polarity;
 0523            break;
 524          case BinaryExpr.ResolvedOpcode.Imp:
 0525            breakDownFurther = !polarity;
 0526            p0 = !p0;
 0527            break;
 528          default:
 0529            break;
 530        }
 0531        if (breakDownFurther) {
 0532          foreach (var c in NormalizedConjuncts(b.E0, p0)) {
 0533            yield return c;
 0534          }
 0535          foreach (var c in NormalizedConjuncts(b.E1, polarity)) {
 0536            yield return c;
 0537          }
 0538          yield break;
 539        }
 0540      }
 541
 542      // Unary expression
 0543      var u = expr as UnaryOpExpr;
 0544      if (u != null && u.Op == UnaryOpExpr.Opcode.Not) {
 0545        foreach (var c in NormalizedConjuncts(u.E, !polarity)) {
 0546          yield return c;
 0547        }
 0548        yield break;
 549      }
 550
 551      // no other case applied, so return the expression or its negation, but first clean it up a little
 0552      b = expr as BinaryExpr;
 0553      if (b != null) {
 554        BinaryExpr.Opcode newOp;
 555        BinaryExpr.ResolvedOpcode newROp;
 556        bool swapOperands;
 0557        switch (b.ResolvedOp) {
 558          case BinaryExpr.ResolvedOpcode.Gt:  // A > B         yield polarity ? (B < A) : (A <= B);
 0559            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0560            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0561            swapOperands = polarity;
 0562            break;
 563          case BinaryExpr.ResolvedOpcode.Ge:  // A >= B        yield polarity ? (B <= A) : (A < B);
 0564            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0565            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0566            swapOperands = polarity;
 0567            break;
 568          case BinaryExpr.ResolvedOpcode.Le:  // A <= B        yield polarity ? (A <= B) : (B < A);
 0569            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0570            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0571            swapOperands = !polarity;
 0572            break;
 573          case BinaryExpr.ResolvedOpcode.Lt:  // A < B         yield polarity ? (A < B) : (B <= A);
 0574            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0575            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0576            swapOperands = !polarity;
 0577            break;
 578          case BinaryExpr.ResolvedOpcode.EqCommon:  // A == B         yield polarity ? (A == B) : (A != B);
 0579            newOp = polarity ? BinaryExpr.Opcode.Eq : BinaryExpr.Opcode.Neq;
 0580            newROp = polarity ? BinaryExpr.ResolvedOpcode.EqCommon : BinaryExpr.ResolvedOpcode.NeqCommon;
 0581            swapOperands = false;
 0582            break;
 583          case BinaryExpr.ResolvedOpcode.NeqCommon:  // A != B         yield polarity ? (A != B) : (A == B);
 0584            newOp = polarity ? BinaryExpr.Opcode.Neq : BinaryExpr.Opcode.Eq;
 0585            newROp = polarity ? BinaryExpr.ResolvedOpcode.NeqCommon : BinaryExpr.ResolvedOpcode.EqCommon;
 0586            swapOperands = false;
 0587            break;
 588          case BinaryExpr.ResolvedOpcode.NotInSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0589            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0590            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSet : BinaryExpr.ResolvedOpcode.InSet;
 0591            swapOperands = false;
 0592            break;
 593          case BinaryExpr.ResolvedOpcode.NotInSeq:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0594            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0595            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSeq : BinaryExpr.ResolvedOpcode.InSeq;
 0596            swapOperands = false;
 0597            break;
 598          case BinaryExpr.ResolvedOpcode.NotInMultiSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0599            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0600            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMultiSet : BinaryExpr.ResolvedOpcode.InMultiSet;
 0601            swapOperands = false;
 0602            break;
 603          case BinaryExpr.ResolvedOpcode.NotInMap:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0604            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0605            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMap : BinaryExpr.ResolvedOpcode.InMap;
 0606            swapOperands = false;
 0607            break;
 608          default:
 0609            goto JUST_RETURN_IT;
 610        }
 0611        if (newROp != b.ResolvedOp || swapOperands) {
 0612          b = new BinaryExpr(b.tok, newOp, swapOperands ? b.E1 : b.E0, swapOperands ? b.E0 : b.E1);
 0613          b.ResolvedOp = newROp;
 0614          b.Type = Type.Bool;
 0615          yield return b;
 0616          yield break;
 617        }
 0618      }
 0619    JUST_RETURN_IT:;
 0620      if (polarity) {
 0621        yield return expr;
 0622      } else {
 0623        expr = new UnaryOpExpr(expr.tok, UnaryOpExpr.Opcode.Not, expr);
 0624        expr.Type = Type.Bool;
 0625        yield return expr;
 0626      }
 0627    }
 628
 629    /// <summary>
 630    /// If the return value is negative, the resulting "e0" and "e1" should not be used.
 631    /// Otherwise, the following is true on return:
 632    /// The new "e0 op e1" is equivalent to the old "e0 op e1".
 633    /// One of "e0" and "e1" is the identifier "boundVars[bvi]"; the return value is either 0 or 1, and indicates which.
 634    /// The other of "e0" and "e1" is an expression whose free variables are not among "boundVars[bvi..]".
 635    /// Ensures that the resulting "e0" and "e1" are not ConcreteSyntaxExpression's.
 636    /// </summary>
 637    static int SanitizeForBoundDiscovery<VT>(List<VT> boundVars, int bvi, BinaryExpr.ResolvedOpcode op,
 638      List<ComprehensionExpr.BoundedPool> knownBounds,
 0639      ref Expression e0, ref Expression e1) where VT : IVariable {
 640      Contract.Requires(boundVars != null);
 641      Contract.Requires(0 <= bvi && bvi < boundVars.Count);
 642      Contract.Requires(knownBounds != null);
 643      Contract.Requires(knownBounds.Count == boundVars.Count);
 644      Contract.Requires(e0 != null);
 645      Contract.Requires(e1 != null);
 646      Contract.Ensures(Contract.Result<int>() < 2);
 647      Contract.Ensures(!(Contract.ValueAtReturn(out e0) is ConcreteSyntaxExpression));
 648      Contract.Ensures(!(Contract.ValueAtReturn(out e1) is ConcreteSyntaxExpression));
 649
 0650      IVariable bv = boundVars[bvi];
 0651      e0 = e0.Resolved;
 0652      e1 = e1.Resolved;
 653
 654      // make an initial assessment of where bv is; to continue, we need bv to appear in exactly one operand
 0655      var fv0 = FreeVariables(e0);
 0656      var fv1 = FreeVariables(e1);
 657      Expression thisSide;
 658      Expression thatSide;
 659      int whereIsBv;
 0660      if (fv0.Contains(bv)) {
 0661        if (fv1.Contains(bv)) {
 0662          return -1;
 663        }
 0664        whereIsBv = 0;
 0665        thisSide = e0;
 0666        thatSide = e1;
 0667      } else if (fv1.Contains(bv)) {
 0668        whereIsBv = 1;
 0669        thisSide = e1;
 0670        thatSide = e0;
 0671      } else {
 0672        return -1;
 673      }
 674
 675      // Next, clean up the side where bv is by adjusting both sides of the expression
 0676      switch (op) {
 677        case BinaryExpr.ResolvedOpcode.EqCommon:
 678        case BinaryExpr.ResolvedOpcode.NeqCommon:
 679        case BinaryExpr.ResolvedOpcode.Gt:
 680        case BinaryExpr.ResolvedOpcode.Ge:
 681        case BinaryExpr.ResolvedOpcode.Le:
 682        case BinaryExpr.ResolvedOpcode.Lt:
 683          // Repeatedly move additive or subtractive terms from thisSide to thatSide
 0684          while (true) {
 0685            var bin = thisSide as BinaryExpr;
 0686            if (bin == null) {
 0687              break; // done simplifying
 688
 0689            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 690              // Change "A+B op C" into either "A op C-B" or "B op C-A", depending on where we find bv among A and B.
 0691              if (!FreeVariables(bin.E1).Contains(bv)) {
 0692                thisSide = bin.E0.Resolved;
 0693                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E1);
 0694              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 0695                thisSide = bin.E1.Resolved;
 0696                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E0);
 0697              } else {
 0698                break; // done simplifying
 699              }
 0700              ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0701              thatSide.Type = bin.Type;
 702
 0703            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 704              // Change "A-B op C" in a similar way.
 0705              if (!FreeVariables(bin.E1).Contains(bv)) {
 706                // change to "A op C+B"
 0707                thisSide = bin.E0.Resolved;
 0708                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Add, thatSide, bin.E1);
 0709                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Add;
 0710              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 711                // In principle, change to "-B op C-A" and then to "B dualOp A-C".  But since we don't want
 712                // to change "op", we instead end with "A-C op B" and switch the mapping of thisSide/thatSide
 713                // to e0/e1 (by inverting "whereIsBv").
 0714                thisSide = bin.E1.Resolved;
 0715                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, bin.E0, thatSide);
 0716                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0717                whereIsBv = 1 - whereIsBv;
 0718              } else {
 0719                break; // done simplifying
 720              }
 0721              thatSide.Type = bin.Type;
 722
 0723            } else {
 0724              break; // done simplifying
 725            }
 0726          }
 0727          break;
 728
 729        default:
 0730          break;
 731      }
 732      // our transformation above maintained the following invariant:
 0733      Contract.Assert(!FreeVariables(thatSide).Contains(bv));
 734
 735      // Now, see if the interesting side is simply bv itself
 0736      if (thisSide is IdentifierExpr && ((IdentifierExpr)thisSide).Var == bv) {
 737        // we're cool
 0738      } else {
 739        // no, the situation is more complicated than we care to understand
 0740        return -1;
 741      }
 742
 743      // Finally, check the bound variables of "thatSide". We allow "thatSide" to
 744      // depend on bound variables that are listed before "bv" (that is, a bound variable
 745      // "boundVars[k]" where "k < bvi"). By construction, "thatSide" does not depend
 746      // on "bv". Generally, for any bound variable "bj" that is listed after "bv"
 747      // (that is, "bj" is some "boundVars[j]" where "bvi < j"), we do not allow
 748      // "thatSide" to depend on "bv", but there is an important exception:
 749      // If
 750      //   *  "op" makes "thatSide" denote an integer upper bound on "bv" (or, analogously,
 751      //      a integer lower bound),
 752      //   *  "thatSide" depends on "bj",
 753      //   *  "thatSide" is monotonic in "bj",
 754      //   *  "bj" has a known integer upper bound "u",
 755      //   *  "u" does not depend on "bv" or any bound variable listed after "bv"
 756      //      (from the way we're constructing bounds, we already know that "u"
 757      //      does not depend on "bj" or any bound variable listed after "bj")
 758      // then we can substitute "u" for "bj" in "thatSide".
 759      // By going from right to left, we can make the rule above slightly more
 760      // liberal by considering a cascade of substitutions.
 0761      var fvThatSide = FreeVariables(thatSide);
 0762      for (int j = boundVars.Count; bvi + 1 <= --j;) {
 0763        if (fvThatSide.Contains(boundVars[j])) {
 0764          if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 0765            var jBounds = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 0766            Expression u = null;
 0767            if (op == BinaryExpr.ResolvedOpcode.Lt || op == BinaryExpr.ResolvedOpcode.Le) {
 0768              u = whereIsBv == 0 ? jBounds.UpperBound : jBounds.LowerBound;
 0769            } else if (op == BinaryExpr.ResolvedOpcode.Gt || op == BinaryExpr.ResolvedOpcode.Ge) {
 0770              u = whereIsBv == 0 ? jBounds.LowerBound : jBounds.UpperBound;
 0771            }
 0772            if (u != null && !FreeVariables(u).Contains(bv) && IsMonotonic(u, boundVars[j], true)) {
 0773              thatSide = Translator.Substitute(thatSide, boundVars[j], u);
 0774              fvThatSide = FreeVariables(thatSide);
 0775              continue;
 776            }
 0777          }
 0778          return -1; // forget about "bv OP thatSide"
 779        }
 0780      }
 781
 782      // As we return, also return the adjusted sides
 0783      if (whereIsBv == 0) {
 0784        e0 = thisSide;
 0785        e1 = thatSide;
 0786      } else {
 0787        e0 = thatSide;
 0788        e1 = thisSide;
 0789      }
 0790      return whereIsBv;
 0791    }
 792
 793    /// <summary>
 794    /// If "position", then returns "true" if "x" occurs only positively in "expr".
 795    /// If "!position", then returns "true" if "x" occurs only negatively in "expr".
 796    /// </summary>
 0797    public static bool IsMonotonic(Expression expr, IVariable x, bool position) {
 798      Contract.Requires(expr != null && expr.Type != null);
 799      Contract.Requires(x != null);
 800
 0801      if (expr is IdentifierExpr identifierExpr) {
 0802        return identifierExpr.Var != x || position;
 0803      } else if (expr is BinaryExpr binaryExpr) {
 0804        if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 0805          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, position);
 0806        } else if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 0807          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, !position);
 808        }
 0809      }
 0810      return !FreeVariables(expr).Contains(x);
 0811    }
 812  }
 813}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/NameResolutionAndTypeInference.cs

#LineLine coverage
 1#define TI_DEBUG_PRINT
 2//-----------------------------------------------------------------------------
 3//
 4// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 5// Copyright by the contributors to the Dafny Project
 6// SPDX-License-Identifier: MIT
 7//
 8//-----------------------------------------------------------------------------
 9using System;
 10using System.Collections.Generic;
 11using System.Linq;
 12using System.Numerics;
 13using System.Diagnostics.Contracts;
 14using System.IO;
 15using System.Reflection;
 16using JetBrains.Annotations;
 17using Microsoft.BaseTypes;
 18using Microsoft.Boogie;
 19using Microsoft.CodeAnalysis.CSharp.Syntax;
 20using Microsoft.Dafny.Plugins;
 21using static Microsoft.Dafny.ErrorRegistry;
 22
 23namespace Microsoft.Dafny {
 24  public partial class Resolver {
 25    /// <summary>
 26    /// There are two rounds of name resolution + type inference. The "initialRound" parameter says which one to do.
 27    /// </summary>
 267028    void ResolveNamesAndInferTypes(List<TopLevelDecl> declarations, bool initialRound) {
 2403029      foreach (TopLevelDecl topd in declarations) {
 534030        Contract.Assert(topd != null);
 534031        Contract.Assert(VisibleInScope(topd));
 534032        Contract.Assert(AllTypeConstraints.Count == 0);
 534033        Contract.Assert(currentClass == null);
 34
 534035        allTypeParameters.PushMarker();
 534036        ResolveTypeParameters(topd.TypeArgs, !initialRound, topd);
 37
 801038        if (initialRound) {
 267039          ResolveNamesAndInferTypesForOneDeclarationInitial(topd);
 534040        } else {
 267041          ResolveNamesAndInferTypesForOneDeclaration(topd);
 267042        }
 43
 534044        allTypeParameters.PopMarker();
 45
 534046        Contract.Assert(AllTypeConstraints.Count == 0);
 534047        Contract.Assert(currentClass == null);
 534048      }
 267049    }
 50
 51    /// <summary>
 52    /// Assumes type parameters of "topd" have already been pushed.
 53    /// </summary>
 267054    void ResolveNamesAndInferTypesForOneDeclarationInitial(TopLevelDecl topd) {
 267055      if (topd is NewtypeDecl newtypeDecl) {
 56        // this check can be done only after it has been determined that the redirected types do not involve cycles
 057        AddXConstraint(newtypeDecl.tok, "NumericType", newtypeDecl.BaseType, "newtypes must be based on some numeric typ
 58        // type check the constraint, if any
 059        if (newtypeDecl.Var != null) {
 060          Contract.Assert(object.ReferenceEquals(newtypeDecl.Var.Type, newtypeDecl.BaseType));  // follows from NewtypeD
 061          Contract.Assert(newtypeDecl.Constraint != null);  // follows from NewtypeDecl invariant
 62
 063          scope.PushMarker();
 064          scope.AllowInstance = false;
 065          var added = scope.Push(newtypeDecl.Var.Name, newtypeDecl.Var);
 066          Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 067          ResolveExpression(newtypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(newtypeDecl, true), fal
 068          Contract.Assert(newtypeDecl.Constraint.Type != null);  // follows from postcondition of ResolveExpression
 069          ConstrainTypeExprBool(newtypeDecl.Constraint, "newtype constraint must be of type bool (instead got {0})");
 070          scope.PopMarker();
 071        }
 072        SolveAllTypeConstraints();
 73
 356074      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 75        // type check the constraint
 89076        Contract.Assert(object.ReferenceEquals(subsetTypeDecl.Var.Type, subsetTypeDecl.Rhs)); // follows from SubsetType
 89077        Contract.Assert(subsetTypeDecl.Constraint != null); // follows from SubsetTypeDecl invariant
 89078        scope.PushMarker();
 89079        scope.AllowInstance = false;
 89080        var added = scope.Push(subsetTypeDecl.Var.Name, subsetTypeDecl.Var);
 89081        Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 89082        ResolveExpression(subsetTypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(subsetTypeDecl, true),
 89083        Contract.Assert(subsetTypeDecl.Constraint.Type != null); // follows from postcondition of ResolveExpression
 89084        ConstrainTypeExprBool(subsetTypeDecl.Constraint, "subset-type constraint must be of type bool (instead got {0})"
 89085        scope.PopMarker();
 89086        SolveAllTypeConstraints();
 89087      }
 88
 445089      if (topd is TopLevelDeclWithMembers cl) {
 178090        ResolveClassMemberBodiesInitial(cl);
 178091      }
 267092    }
 93
 267094    void ResolveNamesAndInferTypesForOneDeclaration(TopLevelDecl topd) {
 267095      if (topd is NewtypeDecl newtypeDecl) {
 096        if (newtypeDecl.Witness != null) {
 097          var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 098          scope.PushMarker();
 099          scope.AllowInstance = false;
 0100          ResolveExpression(newtypeDecl.Witness, new ResolutionContext(codeContext, false));
 0101          scope.PopMarker();
 0102          ConstrainSubtypeRelation(newtypeDecl.Var.Type, newtypeDecl.Witness.Type, newtypeDecl.Witness, "witness express
 0103        }
 0104        SolveAllTypeConstraints();
 105
 3560106      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 890107        if (subsetTypeDecl.Witness != null) {
 0108          var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Gh
 0109          scope.PushMarker();
 0110          scope.AllowInstance = false;
 0111          ResolveExpression(subsetTypeDecl.Witness, new ResolutionContext(codeContext, false));
 0112          scope.PopMarker();
 0113          ConstrainSubtypeRelation(subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type, subsetTypeDecl.Witness,
 0114            "witness expression must have type '{0}' (got '{1}')", subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type)
 0115        }
 890116        SolveAllTypeConstraints();
 117
 2670118      } else if (topd is IteratorDecl iteratorDecl) {
 0119        ResolveIterator(iteratorDecl);
 120
 1780121      } else if (topd is DatatypeDecl dt) {
 122        // resolve any default parameters
 0123        foreach (var ctor in dt.Ctors) {
 0124          scope.PushMarker();
 0125          scope.AllowInstance = false;
 0126          ctor.Formals.ForEach(p => scope.Push(p.Name, p));
 0127          ResolveAttributes(ctor, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 0128          ResolveParameterDefaultValues(ctor.Formals, ResolutionContext.FromCodeContext(dt));
 0129          scope.PopMarker();
 0130        }
 0131      }
 132
 4450133      if (topd is TopLevelDeclWithMembers cl) {
 1780134        ResolveClassMemberBodies(cl);
 1780135      }
 136
 137      // resolve attributes
 2670138      scope.PushMarker();
 2670139      Contract.Assert(currentClass == null);
 2670140      scope.AllowInstance = false;
 2670141      if (topd is IteratorDecl iter) {
 0142        iter.Ins.ForEach(p => scope.Push(p.Name, p));
 0143      }
 2670144      ResolveAttributes(topd, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 2670145      scope.PopMarker();
 2670146    }
 147
 36450148    void EagerAddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 149      Contract.Requires(tok != null);
 150      Contract.Requires(lhs != null);
 151      Contract.Requires(rhs != null);
 152      Contract.Requires(errMsgFormat != null);
 36450153      var lhsNormalized = lhs.Normalize();
 36450154      var rhsNormalized = rhs.Normalize();
 47770155      if (lhsNormalized is TypeProxy lhsProxy && !(rhsNormalized is TypeProxy)) {
 11320156        Contract.Assert(lhsProxy.T == null); // otherwise, lhs.Normalize() above would have kept on going
 11320157        AssignProxyAndHandleItsConstraints(lhsProxy, rhsNormalized, true);
 36450158      } else {
 25130159        AddAssignableConstraint(tok, lhs, rhs, errMsgFormat);
 25130160      }
 36450161    }
 791630162    public void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 163      Contract.Requires(tok != null);
 164      Contract.Requires(lhs != null);
 165      Contract.Requires(rhs != null);
 166      Contract.Requires(errMsgFormat != null);
 791630167      AddXConstraint(tok, "Assignable", lhs, rhs, errMsgFormat);
 791630168    }
 80930169    private void AddXConstraint(IToken tok, string constraintName, Type type, string errMsgFormat) {
 170      Contract.Requires(tok != null);
 171      Contract.Requires(constraintName != null);
 172      Contract.Requires(type != null);
 173      Contract.Requires(errMsgFormat != null);
 80930174      var types = new Type[] { type };
 80930175      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 80930176    }
 372090177    void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, TypeConstraint.ErrorMsg errMsg) {
 178      Contract.Requires(tok != null);
 179      Contract.Requires(lhs != null);
 180      Contract.Requires(rhs != null);
 181      Contract.Requires(errMsg != null);
 372090182      AddXConstraint(tok, "Assignable", lhs, rhs, errMsg);
 372090183    }
 340184    private void AddXConstraint(IToken tok, string constraintName, Type type, TypeConstraint.ErrorMsg errMsg) {
 185      Contract.Requires(tok != null);
 186      Contract.Requires(constraintName != null);
 187      Contract.Requires(type != null);
 188      Contract.Requires(errMsg != null);
 340189      var types = new Type[] { type };
 340190      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 340191    }
 852760192    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, string errMsgFormat) {
 193      Contract.Requires(tok != null);
 194      Contract.Requires(constraintName != null);
 195      Contract.Requires(type0 != null);
 196      Contract.Requires(type1 != null);
 197      Contract.Requires(errMsgFormat != null);
 852760198      var types = new Type[] { type0, type1 };
 852760199      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 852760200    }
 374960201    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, TypeConstraint.ErrorMsg errMs
 202      Contract.Requires(tok != null);
 203      Contract.Requires(constraintName != null);
 204      Contract.Requires(type0 != null);
 205      Contract.Requires(type1 != null);
 206      Contract.Requires(errMsg != null);
 374960207      var types = new Type[] { type0, type1 };
 374960208      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 374960209    }
 1230210    private void AddXConstraint(IToken tok, string constraintName, Type type, Expression expr0, Expression expr1, string
 211      Contract.Requires(tok != null);
 212      Contract.Requires(constraintName != null);
 213      Contract.Requires(type != null);
 214      Contract.Requires(expr0 != null);
 215      Contract.Requires(expr1 != null);
 216      Contract.Requires(errMsgFormat != null);
 1230217      var types = new Type[] { type };
 1230218      var exprs = new Expression[] { expr0, expr1 };
 1230219      AllXConstraints.Add(new XConstraintWithExprs(tok, constraintName, types, exprs, new TypeConstraint.ErrorMsgWithTok
 1230220    }
 221
 222    [System.Diagnostics.Conditional("TI_DEBUG_PRINT")]
 2063010223    void PrintTypeConstraintState(int lbl) {
 4126020224      if (!Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 2063010225        return;
 226      }
 0227      Options.OutputWriter.WriteLine("DEBUG: ---------- type constraints ---------- {0} {1}", lbl, lbl == 0 && currentMe
 0228      foreach (var constraint in AllTypeConstraints) {
 0229        var super = constraint.Super.Normalize();
 0230        var sub = constraint.Sub.Normalize();
 0231        Options.OutputWriter.WriteLine("    {0} :> {1}", super is IntVarietiesSupertype ? "int-like" : super is RealVari
 0232      }
 0233      foreach (var xc in AllXConstraints) {
 0234        Options.OutputWriter.WriteLine("    {0}", xc);
 0235      }
 0236      Options.OutputWriter.WriteLine();
 0237      if (lbl % 2 == 1) {
 0238        Options.OutputWriter.WriteLine("DEBUG: --------------------------------------");
 0239      }
 2063010240    }
 241
 242    /// <summary>
 243    /// Attempts to fully solve all type constraints.
 244    /// Upon failure, reports errors.
 245    /// Clears all constraints.
 246    /// </summary>
 81185247    public void SolveAllTypeConstraints() {
 81185248      PrintTypeConstraintState(0);
 81185249      PartiallySolveTypeConstraints(true);
 81185250      PrintTypeConstraintState(1);
 243555251      foreach (var constraint in AllTypeConstraints) {
 0252        if (Type.IsSupertype(constraint.Super, constraint.Sub)) {
 253          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more sub-typin
 0254          Contract.Assume(false, string.Format("DEBUG: Unexpectedly satisfied supertype relation ({0} :> {1}) |||| ", co
 0255        } else {
 0256          constraint.FlagAsError(this);
 0257        }
 0258      }
 243555259      foreach (var xc in AllXConstraints) {
 0260        if (xc.Confirm(this, true, out var convertedIntoOtherTypeConstraints, out var moreXConstraints)) {
 261          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more XConstrai
 0262          Contract.Assume(false, string.Format("DEBUG: Unexpectedly confirmed XConstraint: {0} |||| ", xc));
 0263        } else if (xc.CouldBeAnything()) {
 264          // suppress the error message; it will later be flagged as an underspecified type
 0265        } else {
 0266          xc.errorMsg.FlagAsError(this);
 0267        }
 0268      }
 81185269      TypeConstraint.ReportErrors(this, reporter);
 81185270      AllTypeConstraints.Clear();
 81185271      AllXConstraints.Clear();
 81185272    }
 273
 274    /// <summary>
 275    /// Adds type constraints for the expressions in the given attributes.
 276    ///
 277    /// If "solveConstraints" is "true", then the constraints are also solved. In this case, it is assumed on entry that
 278    /// prior type constraints. That is, the only type constraints being solved for are the ones in the given attributes
 279    /// </summary>
 2011635280    public void ResolveAttributes(IAttributeBearingDeclaration attributeHost, ResolutionContext resolutionContext, bool 
 281      Contract.Requires(resolutionContext != null);
 282      Contract.Requires(attributeHost != null);
 283
 2011635284      Contract.Assume(!solveConstraints || AllTypeConstraints.Count == 0);
 285
 286      // order does not matter much for resolution, so resolve them in reverse order
 6040245287      foreach (var attr in attributeHost.Attributes.AsEnumerable()) {
 1780288        if (attr is UserSuppliedAttributes) {
 0289          var usa = (UserSuppliedAttributes)attr;
 0290          usa.Recognized = IsRecognizedAttribute(usa, attributeHost);
 0291        }
 3560292        if (attr.Args != null) {
 8010293          foreach (var arg in attr.Args) {
 890294            Contract.Assert(arg != null);
 890295            ResolveExpression(arg, resolutionContext);
 890296          }
 1780297        }
 1780298      }
 299
 2034490300      if (solveConstraints) {
 22855301        SolveAllTypeConstraints();
 22855302      }
 2011635303    }
 304
 305    /// <summary>
 306    /// "IsTwoState" implies that "old" and "fresh" expressions are allowed.
 307    /// </summary>
 2707990308    public void ResolveExpression(Expression expr, ResolutionContext resolutionContext) {
 309
 310#if TEST_TYPE_SYNONYM_TRANSPARENCY
 311      ResolveExpressionX(expr, resolutionContext);
 312      // For testing purposes, change the type of "expr" to a type synonym (mwo-ha-ha-ha!)
 313      var t = expr.Type;
 314      Contract.Assert(t != null);
 315      var sd = new TypeSynonymDecl(expr.tok, "type#synonym#transparency#test", new TypeParameter.TypeParameterCharacteri
 316        new List<TypeParameter>(), resolutionContext.CodeContext.EnclosingModule, t, null);
 317      var ts = new UserDefinedType(expr.tok, "type#synonym#transparency#test", sd, new List<Type>(), null);
 318      expr.DebugTest_ChangeType(ts);
 319    }
 320    public void ResolveExpressionX(Expression expr, ResolutionContext resolutionContext) {
 321#endif
 322      Contract.Requires(expr != null);
 323      Contract.Requires(resolutionContext != null);
 324      Contract.Ensures(expr.Type != null);
 3823355325      if (expr.Type != null) {
 326        // expression has already been resolved
 1115365327        return;
 328      }
 1592625329      DominatingStatementLabels.PushMarker();
 330
 331      // The following cases will resolve the subexpressions and will attempt to assign a type of expr.  However, if err
 332      // and it cannot be determined what the type of expr is, then it is fine to leave expr.Type as null.  In that case
 333      // of this method will assign proxy type to the expression, which reduces the number of error messages that are pr
 334      // while type checking the rest of the program.
 335
 1619065336      if (expr is ParensExpression) {
 26440337        var e = (ParensExpression)expr;
 26440338        ResolveExpression(e.E, resolutionContext);
 26440339        var innerRange = e.E.RangeToken;
 26440340        e.ResolvedExpression = e.E; // Overwrites the range, which is not suitable for ParensExpressions
 26440341        e.E.RangeToken = innerRange;
 26440342        e.Type = e.E.Type;
 343
 1599245344      } else if (expr is ChainingExpression) {
 6620345        var e = (ChainingExpression)expr;
 6620346        ResolveExpression(e.E, resolutionContext);
 6620347        e.ResolvedExpression = e.E;
 6620348        e.Type = e.E.Type;
 349
 1602965350      } else if (expr is NegationExpression) {
 36780351        var e = (NegationExpression)expr;
 36780352        ResolveExpression(e.E, resolutionContext);
 36780353        e.Type = e.E.Type;
 36780354        AddXConstraint(e.E.tok, "NumericOrBitvector", e.E.Type, "type of unary - must be of a numeric or bitvector type 
 355        // Note, e.ResolvedExpression will be filled in during CheckTypeInference, at which time e.Type has been determi
 356
 1864655357      } else if (expr is LiteralExpr) {
 305090358        LiteralExpr e = (LiteralExpr)expr;
 359
 305090360        if (e is StaticReceiverExpr) {
 0361          StaticReceiverExpr eStatic = (StaticReceiverExpr)e;
 0362          ResolveType(eStatic.tok, eStatic.UnresolvedType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, nu
 0363          eStatic.Type = eStatic.UnresolvedType;
 305090364        } else {
 305980365          if (e.Value == null) {
 890366            e.Type = new InferredTypeProxy();
 890367            AddXConstraint(e.tok, "IsNullableRefType", e.Type, "type of 'null' is a reference type, but it is used as {0
 392760368          } else if (e.Value is BigInteger) {
 87670369            var proxy = new InferredTypeProxy();
 87670370            e.Type = proxy;
 87670371            ConstrainSubtypeRelation(new IntVarietiesSupertype(), e.Type, e.tok, "integer literal used as if it had type
 304200372          } else if (e.Value is BaseTypes.BigDec) {
 0373            var proxy = new InferredTypeProxy();
 0374            e.Type = proxy;
 0375            ConstrainSubtypeRelation(new RealVarietiesSupertype(), e.Type, e.tok, "type of real literal is used as {0}",
 298810376          } else if (e.Value is bool) {
 82280377            e.Type = Type.Bool;
 288050378          } else if (e is CharLiteralExpr) {
 71520379            e.Type = Type.Char;
 196980380          } else if (e is StringLiteralExpr) {
 62730381            e.Type = Type.String();
 62730382            ResolveType(e.tok, e.Type, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 62730383          } else {
 0384            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected literal type
 385          }
 305090386        }
 1522785387      } else if (expr is ThisExpr) {
 0388        if (!scope.AllowInstance) {
 0389          reporter.Error(MessageSource.Resolver, expr, "'this' is not allowed in a 'static' context");
 0390        }
 0391        if (currentClass is ClassDecl cd && cd.IsDefaultClass) {
 392          // there's no type
 0393        } else {
 0394          if (currentClass == null) {
 0395            Contract.Assert(reporter.HasErrors);
 0396          } else {
 0397            expr.Type = GetThisType(expr.tok, currentClass);  // do this regardless of scope.AllowInstance, for better e
 0398          }
 0399        }
 400
 1217695401      } else if (expr is IdentifierExpr) {
 0402        var e = (IdentifierExpr)expr;
 0403        e.Var = scope.Find(e.Name);
 0404        if (e.Var != null) {
 0405          expr.Type = e.Var.Type;
 0406        } else {
 0407          reporter.Error(MessageSource.Resolver, expr, "Identifier does not denote a local variable, parameter, or bound
 0408        }
 409
 1376205410      } else if (expr is DatatypeValue) {
 158510411        DatatypeValue dtv = (DatatypeValue)expr;
 158510412        if (!moduleInfo.TopLevels.TryGetValue(dtv.DatatypeName, out var d)) {
 0413          reporter.Error(MessageSource.Resolver, expr.tok, "Undeclared datatype: {0}", dtv.DatatypeName);
 158510414        } else if (d is AmbiguousTopLevelDecl) {
 0415          var ad = (AmbiguousTopLevelDecl)d;
 0416          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 158510417        } else if (!(d is DatatypeDecl)) {
 0418          reporter.Error(MessageSource.Resolver, expr.tok, "Expected datatype: {0}", dtv.DatatypeName);
 158510419        } else {
 158510420          ResolveDatatypeValue(resolutionContext, dtv, (DatatypeDecl)d, null);
 158510421        }
 422
 1362095423      } else if (expr is DisplayExpression) {
 144400424        DisplayExpression e = (DisplayExpression)expr;
 144400425        Type elementType = new InferredTypeProxy() { KeepConstraints = true };
 1503660426        foreach (Expression ee in e.Elements) {
 356820427          ResolveExpression(ee, resolutionContext);
 356820428          Contract.Assert(ee.Type != null);  // follows from postcondition of ResolveExpression
 356820429          ConstrainSubtypeRelation(elementType, ee.Type, ee.tok, "All elements of display must have some common supertyp
 356820430        }
 189900431        if (expr is SetDisplayExpr) {
 45500432          var se = (SetDisplayExpr)expr;
 45500433          expr.Type = new SetType(se.Finite, elementType);
 189520434        } else if (expr is MultiSetDisplayExpr) {
 45120435          expr.Type = new MultiSetType(elementType);
 98900436        } else {
 53780437          expr.Type = new SeqType(elementType);
 53780438        }
 1059185439      } else if (expr is MapDisplayExpr) {
 0440        MapDisplayExpr e = (MapDisplayExpr)expr;
 0441        Type domainType = new InferredTypeProxy();
 0442        Type rangeType = new InferredTypeProxy();
 0443        foreach (ExpressionPair p in e.Elements) {
 0444          ResolveExpression(p.A, resolutionContext);
 0445          Contract.Assert(p.A.Type != null);  // follows from postcondition of ResolveExpression
 0446          ConstrainSubtypeRelation(domainType, p.A.Type, p.A.tok, "All elements of display must have some common superty
 0447          ResolveExpression(p.B, resolutionContext);
 0448          Contract.Assert(p.B.Type != null);  // follows from postcondition of ResolveExpression
 0449          ConstrainSubtypeRelation(rangeType, p.B.Type, p.B.tok, "All elements of display must have some common supertyp
 0450        }
 0451        expr.Type = new MapType(e.Finite, domainType, rangeType);
 1672290452      } else if (expr is NameSegment) {
 757505453        var e = (NameSegment)expr;
 757505454        ResolveNameSegment(e, true, null, resolutionContext, false);
 455
 757505456        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0457          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.Name);
 0458          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 757505459        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0460          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.Name);
 0461          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0462        }
 463
 922535464      } else if (expr is ExprDotName) {
 7750465        var e = (ExprDotName)expr;
 7750466        ResolveDotSuffix(e, true, null, resolutionContext, false);
 7750467        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0468          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.SuffixName);
 0469          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 7750470        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0471          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.SuffixName);
 0472          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0473        }
 474
 165180475      } else if (expr is ApplySuffix) {
 7900476        var e = (ApplySuffix)expr;
 7900477        ResolveApplySuffix(e, resolutionContext, false);
 478
 149530479      } else if (expr is MemberSelectExpr) {
 0480        var e = (MemberSelectExpr)expr;
 0481        ResolveExpression(e.Obj, resolutionContext);
 0482        Contract.Assert(e.Obj.Type != null);  // follows from postcondition of ResolveExpression
 0483        var member = ResolveMember(expr.tok, e.Obj.Type, e.MemberName, out var tentativeReceiverType);
 0484        if (member == null) {
 485          // error has already been reported by ResolveMember
 0486        } else if (member is Function) {
 0487          var fn = member as Function;
 0488          e.Member = fn;
 0489          if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 0490            reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context"
 0491          }
 492          // build the type substitution map
 0493          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0494          e.TypeApplication_JustMember = new List<Type>();
 495          Dictionary<TypeParameter, Type> subst;
 0496          var ctype = tentativeReceiverType as UserDefinedType;
 0497          if (ctype == null) {
 0498            subst = new Dictionary<TypeParameter, Type>();
 0499          } else {
 0500            subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0501          }
 0502          foreach (var tp in fn.TypeArgs) {
 0503            Type prox = new InferredTypeProxy();
 0504            subst[tp] = prox;
 0505            e.TypeApplication_JustMember.Add(prox);
 0506          }
 0507          subst = BuildTypeArgumentSubstitute(subst);
 0508          e.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 0509        } else if (member is Field) {
 0510          var field = (Field)member;
 0511          e.Member = field;
 0512          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0513          e.TypeApplication_JustMember = new List<Type>();
 0514          if (e.Obj is StaticReceiverExpr && !field.IsStatic) {
 0515            reporter.Error(MessageSource.Resolver, expr, "a field must be selected via an object, not just a class name"
 0516          }
 0517          var ctype = tentativeReceiverType as UserDefinedType;
 0518          if (ctype == null) {
 0519            e.Type = field.Type;
 0520          } else {
 0521            Contract.Assert(ctype.ResolvedClass != null); // follows from postcondition of ResolveMember
 522            // build the type substitution map
 0523            var subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0524            e.Type = field.Type.Subst(subst);
 0525          }
 0526        } else {
 0527          reporter.Error(MessageSource.Resolver, expr, "member {0} in type {1} does not refer to a field or a function",
 0528        }
 529
 155410530      } else if (expr is SeqSelectExpr) {
 13780531        SeqSelectExpr e = (SeqSelectExpr)expr;
 13780532        ResolveSeqSelectExpr(e, resolutionContext);
 533
 141630534      } else if (expr is MultiSelectExpr) {
 0535        MultiSelectExpr e = (MultiSelectExpr)expr;
 536
 0537        ResolveExpression(e.Array, resolutionContext);
 0538        Contract.Assert(e.Array.Type != null);  // follows from postcondition of ResolveExpression
 0539        Contract.Assert(e.Array.Type.TypeArgs != null);  // if it is null, should make a 1-element list with a Proxy
 0540        Type elementType = e.Array.Type.TypeArgs.Count > 0 ?
 0541          e.Array.Type.TypeArgs[0] :
 0542          new InferredTypeProxy();
 0543        ConstrainSubtypeRelation(ResolvedArrayType(e.Array.tok, e.Indices.Count, elementType, resolutionContext, true), 
 0544          "array selection requires an array{0} (got {1})", e.Indices.Count, e.Array.Type);
 0545        int i = 0;
 0546        foreach (Expression idx in e.Indices) {
 0547          Contract.Assert(idx != null);
 0548          ResolveExpression(idx, resolutionContext);
 0549          Contract.Assert(idx.Type != null);  // follows from postcondition of ResolveExpression
 0550          ConstrainToIntegerType(idx, true, "array selection requires integer- or bitvector-based numeric indices (got {
 0551          i++;
 0552        }
 0553        e.Type = elementType;
 554
 129080555      } else if (expr is SeqUpdateExpr) {
 1230556        SeqUpdateExpr e = (SeqUpdateExpr)expr;
 1230557        ResolveExpression(e.Seq, resolutionContext);
 1230558        Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 1230559        ResolveExpression(e.Index, resolutionContext);
 1230560        ResolveExpression(e.Value, resolutionContext);
 1230561        AddXConstraint(expr.tok, "SeqUpdatable", e.Seq.Type, e.Index, e.Value, "update requires a sequence, map, or mult
 1230562        expr.Type = new InferredTypeProxy(); // drop type constraints
 1230563        ConstrainSubtypeRelation(
 1230564          super: expr.Type, sub: e.Seq.Type, // expr.Type generalizes e.Seq.Type by dropping constraints
 1230565          exprForToken: expr,
 1230566          msg: "Update expression used with type '{0}'", e.Seq.Type);
 127850567      } else if (expr is DatatypeUpdateExpr) {
 0568        var e = (DatatypeUpdateExpr)expr;
 0569        ResolveExpression(e.Root, resolutionContext);
 0570        var ty = PartiallyResolveTypeForMemberSelection(expr.tok, e.Root.Type);
 0571        if (!ty.IsDatatype) {
 0572          reporter.Error(MessageSource.Resolver, expr, "datatype update expression requires a root expression of a datat
 0573        } else {
 0574          var (ghostLet, compiledLet) = ResolveDatatypeUpdate(expr.tok, e.Root, ty.AsDatatype, e.Updates, resolutionCont
 0575            out var members, out var legalSourceConstructors);
 0576          Contract.Assert((ghostLet == null) == (compiledLet == null));
 0577          if (ghostLet != null) {
 0578            e.ResolvedExpression = ghostLet; // this might be replaced by e.ResolvedCompiledExpression in CheckIsCompila
 0579            e.ResolvedCompiledExpression = compiledLet;
 0580            e.Members = members;
 0581            e.LegalSourceConstructors = legalSourceConstructors;
 0582            expr.Type = ghostLet.Type;
 0583          }
 0584        }
 585
 126620586      } else if (expr is FunctionCallExpr) {
 0587        var e = (FunctionCallExpr)expr;
 0588        ResolveFunctionCallExpr(e, resolutionContext);
 589
 126620590      } else if (expr is ApplyExpr) {
 0591        var e = (ApplyExpr)expr;
 0592        ResolveExpression(e.Function, resolutionContext);
 0593        foreach (var arg in e.Args) {
 0594          ResolveExpression(arg, resolutionContext);
 0595        }
 596
 597        // TODO: the following should be replaced by a type-class constraint that constrains the types of e.Function, e.
 0598        var fnType = e.Function.Type.AsArrowType;
 0599        if (fnType == null) {
 0600          reporter.Error(MessageSource.Resolver, e.tok,
 0601            "non-function expression (of type {0}) is called with parameters", e.Function.Type);
 0602        } else if (fnType.Arity != e.Args.Count) {
 0603          reporter.Error(MessageSource.Resolver, e.tok,
 0604            "wrong number of arguments to function application (function type '{0}' expects {1}, got {2})", fnType,
 0605            fnType.Arity, e.Args.Count);
 0606        } else {
 0607          for (var i = 0; i < fnType.Arity; i++) {
 0608            AddAssignableConstraint(e.Args[i].tok, fnType.Args[i], e.Args[i].Type,
 0609              "type mismatch for argument" + (fnType.Arity == 1 ? "" : " " + i) + " (function expects {0}, got {1})");
 0610          }
 0611        }
 612
 0613        expr.Type = fnType == null ? new InferredTypeProxy() : fnType.Result;
 614
 126620615      } else if (expr is SeqConstructionExpr) {
 0616        var e = (SeqConstructionExpr)expr;
 0617        var elementType = e.ExplicitElementType ?? new InferredTypeProxy();
 0618        ResolveType(e.tok, elementType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0619        ResolveExpression(e.N, resolutionContext);
 0620        ConstrainToIntegerType(e.N, false, "sequence construction must use an integer-based expression for the sequence 
 0621        ResolveExpression(e.Initializer, resolutionContext);
 0622        var arrowType = new ArrowType(e.tok, builtIns.ArrowTypeDecls[1], new List<Type>() { builtIns.Nat() }, elementTyp
 0623        var hintString = " (perhaps write '_ =>' in front of the expression you gave in order to make it an arrow type)"
 0624        ConstrainSubtypeRelation(arrowType, e.Initializer.Type, e.Initializer, "sequence-construction initializer expres
 0625          arrowType, e.Initializer.Type, new LazyString_OnTypeEquals(elementType, e.Initializer.Type, hintString));
 0626        expr.Type = new SeqType(elementType);
 627
 126950628      } else if (expr is MultiSetFormingExpr) {
 330629        MultiSetFormingExpr e = (MultiSetFormingExpr)expr;
 330630        ResolveExpression(e.E, resolutionContext);
 330631        var elementType = new InferredTypeProxy();
 330632        AddXConstraint(e.E.tok, "MultiSetConvertible", e.E.Type, elementType, "can only form a multiset from a seq or se
 330633        expr.Type = new MultiSetType(elementType);
 634
 126620635      } else if (expr is OldExpr) {
 0636        var e = (OldExpr)expr;
 0637        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "old", resolutionContext);
 0638        ResolveExpression(e.E, new ResolutionContext(resolutionContext.CodeContext, false) with { InOld = true });
 0639        expr.Type = e.E.Type;
 640
 126290641      } else if (expr is UnchangedExpr) {
 0642        var e = (UnchangedExpr)expr;
 0643        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "unchanged", resolutionContext);
 0644        foreach (var fe in e.Frame) {
 0645          ResolveFrameExpression(fe, FrameExpressionUse.Unchanged, resolutionContext);
 0646        }
 0647        expr.Type = Type.Bool;
 648
 126290649      } else if (expr is FreshExpr) {
 0650        var e = (FreshExpr)expr;
 0651        ResolveExpression(e.E, resolutionContext);
 0652        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "fresh", resolutionContext);
 653        // the type of e.E must be either an object or a set/seq of objects
 0654        AddXConstraint(expr.tok, "Freshable", e.E.Type, "the argument of a fresh expression must denote an object or a s
 0655        expr.Type = Type.Bool;
 656
 136050657      } else if (expr is UnaryOpExpr) {
 9760658        var e = (UnaryOpExpr)expr;
 9760659        ResolveExpression(e.E, resolutionContext);
 9760660        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 9760661        switch (e.Op) {
 662          case UnaryOpExpr.Opcode.Not:
 260663            AddXConstraint(e.E.tok, "BooleanBits", e.E.Type, "logical/bitwise negation expects a boolean or bitvector ar
 260664            expr.Type = e.E.Type;
 260665            break;
 666          case UnaryOpExpr.Opcode.Cardinality:
 9500667            AddXConstraint(expr.tok, "Sizeable", e.E.Type, "size operator expects a collection argument (instead got {0}
 9500668            expr.Type = Type.Int;
 9500669            break;
 670          case UnaryOpExpr.Opcode.Allocated:
 671            // the argument is allowed to have any type at all
 0672            expr.Type = Type.Bool;
 0673            if (2 <= Options.Allocated &&
 0674              ((resolutionContext.CodeContext is Function && !resolutionContext.InOld) || resolutionContext.CodeContext 
 0675              var declKind = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) is RedirectingTypeDecl redir ? red
 0676              reporter.Error(MessageSource.Resolver, expr, "a {0} definition is not allowed to depend on the set of allo
 0677            }
 0678            break;
 679          default:
 0680            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected unary operator
 681        }
 682
 683        // We do not have enough information to compute `e.ResolvedOp` yet.
 684        // For binary operators the computation happens in `CheckTypeInference`.
 685        // For unary operators it happens lazily in the getter of `e.ResolvedOp`.
 127220686      } else if (expr is ConversionExpr) {
 930687        var e = (ConversionExpr)expr;
 930688        ResolveExpression(e.E, resolutionContext);
 930689        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 930690        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 1860691        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 1860692          if (e.ToType.IsNumericBased(Type.NumericPersuasion.Int)) {
 930693            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an int-based typ
 930694          } else if (e.ToType.IsNumericBased(Type.NumericPersuasion.Real)) {
 0695            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a real-based typ
 0696          } else if (e.ToType.IsBitVectorType) {
 0697            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a bitvector-base
 0698          } else if (e.ToType.IsCharType) {
 0699            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a char type is a
 0700          } else if (e.ToType.IsBigOrdinalType) {
 0701            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an ORDINAL type 
 0702          } else if (e.ToType.IsRefType) {
 0703            AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type cast to reference type '{0}' must be from an exp
 0704          } else {
 0705            reporter.Error(MessageSource.Resolver, expr, "type conversions are not supported to this type (got {0})", e.
 0706          }
 930707          e.Type = e.ToType;
 930708        } else {
 0709          e.Type = new InferredTypeProxy();
 0710        }
 711
 116530712      } else if (expr is TypeTestExpr) {
 0713        var e = (TypeTestExpr)expr;
 0714        ResolveExpression(e.E, resolutionContext);
 0715        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 0716        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 0717        AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type test for type '{0}' must be from an expression assig
 0718        e.Type = Type.Bool;
 719
 180200720      } else if (expr is BinaryExpr) {
 721
 64600722        BinaryExpr e = (BinaryExpr)expr;
 64600723        ResolveExpression(e.E0, resolutionContext);
 64600724        Contract.Assert(e.E0.Type != null);  // follows from postcondition of ResolveExpression
 64600725        ResolveExpression(e.E1, resolutionContext);
 64600726        Contract.Assert(e.E1.Type != null);  // follows from postcondition of ResolveExpression
 727
 64600728        switch (e.Op) {
 729          case BinaryExpr.Opcode.Iff:
 730          case BinaryExpr.Opcode.Imp:
 731          case BinaryExpr.Opcode.Exp:
 732          case BinaryExpr.Opcode.And:
 16590733          case BinaryExpr.Opcode.Or: {
 16590734              ConstrainSubtypeRelation(Type.Bool, e.E0.Type, expr, "first argument to {0} must be of type bool (instead 
 16590735              var secondArgumentDescription = e.E1.tok is QuantifiedVariableRangeToken
 16590736                ? "range of quantified variable" : "second argument to {0}";
 16590737              ConstrainSubtypeRelation(Type.Bool, e.E1.Type, expr, secondArgumentDescription + " must be of type bool (i
 16590738              expr.Type = Type.Bool;
 16590739              break;
 740            }
 741
 742          case BinaryExpr.Opcode.Eq:
 743          case BinaryExpr.Opcode.Neq:
 2800744            AddXConstraint(expr.tok, "Equatable", e.E0.Type, e.E1.Type, "arguments must have comparable types (got {0} a
 2800745            expr.Type = Type.Bool;
 2800746            break;
 747
 748          case BinaryExpr.Opcode.Disjoint:
 1150749            Type disjointArgumentsType = new InferredTypeProxy();
 1150750            ConstrainSubtypeRelation(disjointArgumentsType, e.E0.Type, expr, "arguments to {2} must have a common supert
 1150751            ConstrainSubtypeRelation(disjointArgumentsType, e.E1.Type, expr, "arguments to {2} must have a common supert
 1150752            AddXConstraint(expr.tok, "Disjointable", disjointArgumentsType, "arguments must be of a set or multiset type
 1150753            expr.Type = Type.Bool;
 1150754            break;
 755
 756          case BinaryExpr.Opcode.Lt:
 23560757          case BinaryExpr.Opcode.Le: {
 23560758              if (e.Op == BinaryExpr.Opcode.Lt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0759                AddXConstraint(expr.tok, "RankOrderable", e.E0.Type, e.E1.Type, "arguments to rank comparison must be da
 0760                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankLt;
 23560761              } else {
 23560762                var cmpType = new InferredTypeProxy();
 23560763                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 23560764                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 23560765                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 23560766                AddXConstraint(expr.tok, "Orderable_Lt", e.E0.Type, e.E1.Type,
 23560767                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 23560768              }
 23560769              expr.Type = Type.Bool;
 23560770            }
 23560771            break;
 772
 773          case BinaryExpr.Opcode.Gt:
 1310774          case BinaryExpr.Opcode.Ge: {
 1310775              if (e.Op == BinaryExpr.Opcode.Gt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0776                AddXConstraint(expr.tok, "RankOrderable", e.E1.Type, e.E0.Type, "arguments to rank comparison must be da
 0777                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankGt;
 1310778              } else {
 1310779                var cmpType = new InferredTypeProxy();
 1310780                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 1310781                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 1310782                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 1310783                AddXConstraint(expr.tok, "Orderable_Gt", e.E0.Type, e.E1.Type,
 1310784                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 1310785              }
 1310786              expr.Type = Type.Bool;
 1310787            }
 1310788            break;
 789
 790          case BinaryExpr.Opcode.LeftShift:
 0791          case BinaryExpr.Opcode.RightShift: {
 0792              expr.Type = new InferredTypeProxy();
 0793              AddXConstraint(e.tok, "IsBitvector", expr.Type, "type of " + BinaryExpr.OpcodeString(e.Op) + " must be a b
 0794              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to " + BinaryExpr.OpcodeSt
 0795              AddXConstraint(expr.tok, "IntLikeOrBitvector", e.E1.Type, "type of right argument to " + BinaryExpr.Opcode
 0796            }
 0797            break;
 798
 13750799          case BinaryExpr.Opcode.Add: {
 13750800              expr.Type = new InferredTypeProxy();
 13750801              AddXConstraint(e.tok, "Plussable", expr.Type, "type of + must be of a numeric type, a bitvector type, ORDI
 13750802              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to + ({0}) must agree with
 13750803              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to + ({0}) must agree wit
 13750804            }
 13750805            break;
 806
 1340807          case BinaryExpr.Opcode.Sub: {
 1340808              expr.Type = new InferredTypeProxy();
 1340809              AddXConstraint(e.tok, "Minusable", expr.Type, "type of - must be of a numeric type, bitvector type, ORDINA
 1340810              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to - ({0}) must agree with
 811              // The following handles map subtraction, but does not in an unfortunately restrictive way.
 812              // First, it would be nice to delay the decision of it this is a map subtraction or not. This settles
 813              // for the simple way to decide based on what is currently known about the result type, which is also
 814              // done, for example, when deciding if "<" denotes rank ordering on datatypes.
 815              // Second, for map subtraction, it would be nice to allow the right-hand operand to be either a set or
 816              // an iset. That would also lead to further complexity in the code, so this code restricts the right-hand
 817              // operand to be a set.
 1340818              var eType = PartiallyResolveTypeForMemberSelection(expr.tok, expr.Type).AsMapType;
 1340819              if (eType != null) {
 820                // allow "map - set == map"
 0821                var expected = new SetType(true, eType.Domain);
 0822                ConstrainSubtypeRelation(expected, e.E1.Type, expr.tok, "map subtraction expects right-hand operand to h
 1340823              } else {
 1340824                ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to - ({0}) must agree w
 1340825              }
 1340826            }
 1340827            break;
 828
 770829          case BinaryExpr.Opcode.Mul: {
 770830              expr.Type = new InferredTypeProxy();
 770831              AddXConstraint(e.tok, "Mullable", expr.Type, "type of * must be of a numeric type, bitvector type, or a se
 770832              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to * ({0}) must agree with
 770833              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to * ({0}) must agree wit
 770834            }
 770835            break;
 836
 837          case BinaryExpr.Opcode.In:
 838          case BinaryExpr.Opcode.NotIn:
 1550839            var subjectDescription = e.E1.tok is QuantifiedVariableDomainToken
 1550840              ? "domain of quantified variable" : "second argument to \"" + BinaryExpr.OpcodeString(e.Op) + "\"";
 1550841            AddXConstraint(expr.tok, "Innable", e.E1.Type, e.E0.Type, subjectDescription + " must be a set, multiset, or
 1550842            expr.Type = Type.Bool;
 1550843            break;
 844
 845          case BinaryExpr.Opcode.Div:
 890846            expr.Type = new InferredTypeProxy();
 890847            AddXConstraint(expr.tok, "NumericOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 890848            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 890849              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 890850              e.E0.Type, expr.Type);
 890851            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 890852              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 890853              e.E1.Type, expr.Type);
 890854            break;
 855
 856          case BinaryExpr.Opcode.Mod:
 890857            expr.Type = new InferredTypeProxy();
 890858            AddXConstraint(expr.tok, "IntLikeOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 890859            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 890860              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 890861              e.E0.Type, expr.Type);
 890862            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 890863              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 890864              e.E1.Type, expr.Type);
 890865            break;
 866
 867          case BinaryExpr.Opcode.BitwiseAnd:
 868          case BinaryExpr.Opcode.BitwiseOr:
 869          case BinaryExpr.Opcode.BitwiseXor:
 0870            expr.Type = NewIntegerBasedProxy(expr.tok);
 0871            var errFormat = "first argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instea
 0872            ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr, errFormat, e.E0.Type);
 0873            AddXConstraint(expr.tok, "IsBitvector", e.E0.Type, errFormat);
 0874            errFormat = "second argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instead g
 0875            ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr, errFormat, e.E1.Type);
 0876            AddXConstraint(expr.tok, "IsBitvector", e.E1.Type, errFormat);
 0877            break;
 878
 879          default:
 0880            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 881        }
 882        // We should also fill in e.ResolvedOp, but we may not have enough information for that yet.  So, instead, delay
 883        // setting e.ResolvedOp until inside CheckTypeInference.
 884
 115600885      } else if (expr is TernaryExpr) {
 0886        var e = (TernaryExpr)expr;
 0887        ResolveExpression(e.E0, resolutionContext);
 0888        ResolveExpression(e.E1, resolutionContext);
 0889        ResolveExpression(e.E2, resolutionContext);
 0890        switch (e.Op) {
 891          case TernaryExpr.Opcode.PrefixEqOp:
 892          case TernaryExpr.Opcode.PrefixNeqOp:
 0893            AddXConstraint(expr.tok, "IntOrORDINAL", e.E0.Type, "prefix-equality limit argument must be an ORDINAL or in
 0894            AddXConstraint(expr.tok, "Equatable", e.E1.Type, e.E2.Type, "arguments must have the same type (got {0} and 
 0895            AddXConstraint(expr.tok, "IsCoDatatype", e.E1.Type, "arguments to prefix equality must be codatatypes (inste
 0896            expr.Type = Type.Bool;
 0897            break;
 898          default:
 0899            Contract.Assert(false);  // unexpected ternary operator
 0900            break;
 901        }
 902
 87450903      } else if (expr is LetExpr) {
 36450904        var e = (LetExpr)expr;
 72900905        if (e.Exact) {
 218700906          foreach (var rhs in e.RHSs) {
 36450907            ResolveExpression(rhs, resolutionContext);
 36450908          }
 36450909          scope.PushMarker();
 36450910          if (e.LHSs.Count != e.RHSs.Count) {
 0911            reporter.Error(MessageSource.Resolver, expr, "let expression must have same number of LHSs (found {0}) as RH
 0912          }
 36450913          var i = 0;
 218700914          foreach (var lhs in e.LHSs) {
 36450915            var rhsType = i < e.RHSs.Count ? e.RHSs[i].Type : new InferredTypeProxy();
 36450916            ResolveCasePattern(lhs, rhsType, resolutionContext);
 917            // Check for duplicate names now, because not until after resolving the case pattern do we know if identifie
 36450918            var c = 0;
 218700919            foreach (var v in lhs.Vars) {
 36450920              ScopePushAndReport(scope, v, "let-variable");
 36450921              c++;
 36450922            }
 36450923            if (c == 0) {
 924              // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constan
 0925              reporter.Error(MessageSource.Resolver, lhs.tok, "LHS is a constant literal; to be legal, it must introduce
 0926            }
 36450927            i++;
 36450928          }
 36450929        } else {
 930          // let-such-that expression
 0931          if (e.RHSs.Count != 1) {
 0932            reporter.Error(MessageSource.Resolver, expr, "let-such-that expression must have just one RHS (found {0})", 
 0933          }
 934          // the bound variables are in scope in the RHS of a let-such-that expression
 0935          scope.PushMarker();
 0936          foreach (var lhs in e.LHSs) {
 0937            Contract.Assert(lhs.Var != null);  // the parser already checked that every LHS is a BoundVar, not a general
 0938            var v = lhs.Var;
 0939            ScopePushAndReport(scope, v, "let-variable");
 0940            ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0941          }
 0942          foreach (var rhs in e.RHSs) {
 0943            ResolveExpression(rhs, resolutionContext);
 0944            ConstrainTypeExprBool(rhs, "type of RHS of let-such-that expression must be boolean (got {0})");
 0945          }
 0946        }
 36450947        ResolveExpression(e.Body, resolutionContext);
 36450948        ResolveAttributes(e, resolutionContext);
 36450949        scope.PopMarker();
 36450950        expr.Type = e.Body.Type;
 51000951      } else if (expr is LetOrFailExpr) {
 0952        var e = (LetOrFailExpr)expr;
 0953        ResolveLetOrFailExpr(e, resolutionContext);
 14550954      } else if (expr is QuantifierExpr) {
 0955        var e = (QuantifierExpr)expr;
 0956        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 0957        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0958        scope.PushMarker();
 0959        foreach (BoundVar v in e.BoundVars) {
 0960          ScopePushAndReport(scope, v, "bound-variable");
 0961          var option = new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies);
 0962          ResolveType(v.tok, v.Type, resolutionContext, option, null);
 0963        }
 0964        if (e.Range != null) {
 0965          ResolveExpression(e.Range, resolutionContext);
 0966          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0967          ConstrainTypeExprBool(e.Range, "range of quantifier must be of type bool (instead got {0})");
 0968        }
 0969        ResolveExpression(e.Term, resolutionContext);
 0970        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 0971        ConstrainTypeExprBool(e.Term, "body of quantifier must be of type bool (instead got {0})");
 972        // Since the body is more likely to infer the types of the bound variables, resolve it
 973        // first (above) and only then resolve the attributes (below).
 0974        ResolveAttributes(e, resolutionContext);
 0975        scope.PopMarker();
 0976        expr.Type = Type.Bool;
 977
 14550978      } else if (expr is SetComprehension) {
 0979        var e = (SetComprehension)expr;
 0980        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0981        scope.PushMarker();
 0982        foreach (BoundVar v in e.BoundVars) {
 0983          ScopePushAndReport(scope, v, "bound-variable");
 0984          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0985          var inferredProxy = v.Type as InferredTypeProxy;
 0986          if (inferredProxy != null) {
 0987            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 0988          }
 0989        }
 0990        ResolveExpression(e.Range, resolutionContext);
 0991        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0992        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 0993        ResolveExpression(e.Term, resolutionContext);
 0994        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 995
 0996        ResolveAttributes(e, resolutionContext);
 0997        scope.PopMarker();
 0998        expr.Type = new SetType(e.Finite, e.Term.Type);
 999
 145501000      } else if (expr is MapComprehension) {
 01001        var e = (MapComprehension)expr;
 01002        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 01003        scope.PushMarker();
 01004        Contract.Assert(e.BoundVars.Count == 1 || (1 < e.BoundVars.Count && e.TermLeft != null));
 01005        foreach (BoundVar v in e.BoundVars) {
 01006          ScopePushAndReport(scope, v, "bound-variable");
 01007          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 01008          var inferredProxy = v.Type as InferredTypeProxy;
 01009          if (inferredProxy != null) {
 01010            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 01011          }
 01012        }
 01013        ResolveExpression(e.Range, resolutionContext);
 01014        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01015        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 01016        if (e.TermLeft != null) {
 01017          ResolveExpression(e.TermLeft, resolutionContext);
 01018          Contract.Assert(e.TermLeft.Type != null);  // follows from postcondition of ResolveExpression
 01019        }
 01020        ResolveExpression(e.Term, resolutionContext);
 01021        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 1022
 01023        ResolveAttributes(e, resolutionContext);
 01024        scope.PopMarker();
 01025        expr.Type = new MapType(e.Finite, e.TermLeft != null ? e.TermLeft.Type : e.BoundVars[0].Type, e.Term.Type);
 1026
 193101027      } else if (expr is LambdaExpr) {
 47601028        var e = (LambdaExpr)expr;
 47601029        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 47601030        scope.PushMarker();
 490801031        foreach (BoundVar v in e.BoundVars) {
 116001032          ScopePushAndReport(scope, v, "bound-variable");
 116001033          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 116001034        }
 1035
 47601036        if (e.Range != null) {
 01037          ResolveExpression(e.Range, resolutionContext);
 01038          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01039          ConstrainTypeExprBool(e.Range, "Precondition must be boolean (got {0})");
 01040        }
 142801041        foreach (var read in e.Reads) {
 01042          ResolveFrameExpression(read, FrameExpressionUse.Reads, resolutionContext);
 01043        }
 47601044        ResolveExpression(e.Term, resolutionContext);
 47601045        Contract.Assert(e.Term.Type != null);
 47601046        scope.PopMarker();
 163601047        expr.Type = SelectAppropriateArrowType(e.tok, e.BoundVars.ConvertAll(v => v.Type), e.Body.Type, e.Reads.Count !=
 145501048      } else if (expr is WildcardExpr) {
 01049        expr.Type = new SetType(true, builtIns.ObjectQ());
 97901050      } else if (expr is StmtExpr) {
 01051        var e = (StmtExpr)expr;
 01052        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 1053
 01054        ResolveStatement(e.S, resolutionContext);
 01055        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 01056          var r = e.S as UpdateStmt;
 01057          if (r != null && r.ResolvedStatements.Count == 1) {
 01058            var call = r.ResolvedStatements[0] as CallStmt;
 01059            if (call.Method is TwoStateLemma && !resolutionContext.IsTwoState) {
 01060              reporter.Error(MessageSource.Resolver, call, "two-state lemmas can only be used in two-state contexts");
 01061            }
 01062          }
 01063        }
 1064
 01065        ResolveExpression(e.E, resolutionContext);
 01066        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 01067        expr.Type = e.E.Type;
 1068
 195801069      } else if (expr is ITEExpr) {
 97901070        ITEExpr e = (ITEExpr)expr;
 97901071        ResolveExpression(e.Test, resolutionContext);
 97901072        Contract.Assert(e.Test.Type != null);  // follows from postcondition of ResolveExpression
 97901073        ResolveExpression(e.Thn, resolutionContext);
 97901074        Contract.Assert(e.Thn.Type != null);  // follows from postcondition of ResolveExpression
 97901075        ResolveExpression(e.Els, resolutionContext);
 97901076        Contract.Assert(e.Els.Type != null);  // follows from postcondition of ResolveExpression
 97901077        ConstrainTypeExprBool(e.Test, "guard condition in if-then-else expression must be a boolean (instead got {0})");
 97901078        expr.Type = new InferredTypeProxy();
 97901079        ConstrainSubtypeRelation(expr.Type, e.Thn.Type, expr, "the two branches of an if-then-else expression must have 
 97901080        ConstrainSubtypeRelation(expr.Type, e.Els.Type, expr, "the two branches of an if-then-else expression must have 
 1081
 97901082      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 01083        ResolveNestedMatchExpr(nestedMatchExpr, resolutionContext);
 01084      } else {
 01085        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected expression
 1086      }
 1087
 15926251088      if (expr.Type == null) {
 1089        // some resolution error occurred
 01090        expr.Type = new InferredTypeProxy();
 01091      }
 1092
 15926251093      DominatingStatementLabels.PopMarker();
 27079901094    }
 1095
 457101096    void ResolveTypeParameters(List<TypeParameter/*!*/>/*!*/ tparams, bool emitErrors, TypeParameter.ParentType/*!*/ par
 1097      Contract.Requires(tparams != null);
 1098      Contract.Requires(parent != null);
 1099      // push non-duplicated type parameter names
 457101100      int index = 0;
 1918651101      foreach (TypeParameter tp in tparams) {
 275901102        if (emitErrors) {
 1103          // we're seeing this TypeParameter for the first time
 93451104          tp.Parent = parent;
 93451105          tp.PositionalIndex = index;
 93451106        }
 182451107        var r = allTypeParameters.Push(tp.Name, tp);
 275901108        if (emitErrors) {
 93451109          if (r == Scope<TypeParameter>.PushResult.Duplicate) {
 01110            reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tp, "Duplicate type-parameter name: {0}", tp.Na
 93451111          } else if (r == Scope<TypeParameter>.PushResult.Shadow) {
 01112            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tp.tok, "Shadowed type-parameter name: {0}", 
 01113          }
 93451114        }
 182451115      }
 457101116    }
 1117
 1039101118    private bool ConstrainSubtypeRelation(Type super, Type sub, Expression exprForToken, string msg, params object[] msg
 1119      Contract.Requires(sub != null);
 1120      Contract.Requires(super != null);
 1121      Contract.Requires(exprForToken != null);
 1122      Contract.Requires(msg != null);
 1123      Contract.Requires(msgArgs != null);
 1039101124      return ConstrainSubtypeRelation(super, sub, exprForToken.tok, msg, msgArgs);
 1039101125    }
 1126
 250301127    public void ConstrainTypeExprBool(Expression e, string msg) {
 1128      Contract.Requires(e != null);
 1129      Contract.Requires(msg != null);  // expected to have a {0} part
 250301130      ConstrainSubtypeRelation(Type.Bool, e.Type, e, msg, e.Type);
 250301131    }
 1132
 6052301133    public bool ConstrainSubtypeRelation(Type super, Type sub, IToken tok, string msg, params object[] msgArgs) {
 1134      Contract.Requires(sub != null);
 1135      Contract.Requires(super != null);
 1136      Contract.Requires(tok != null);
 1137      Contract.Requires(msg != null);
 1138      Contract.Requires(msgArgs != null);
 6052301139      return ConstrainSubtypeRelation(super, sub, new TypeConstraint.ErrorMsgWithToken(tok, msg, msgArgs));
 6052301140    }
 1141
 5026701142    private void ConstrainAssignable(NonProxyType lhs, Type rhs, TypeConstraint.ErrorMsg errMsg, out bool moreXConstrain
 1143      Contract.Requires(lhs != null);
 1144      Contract.Requires(rhs != null);
 1145      Contract.Requires(errMsg != null);
 1146
 5026701147      DetermineRootLeaf(lhs, out var isRoot, out _, out _, out _);
 10020901148      if (isRoot) {
 4994201149        ConstrainSubtypeRelation(lhs, rhs, errMsg, true, allowDecisions);
 4994201150        moreXConstraints = false;
 5026701151      } else {
 32501152        var lhsWithProxyArgs = Type.HeadWithProxyArgs(lhs);
 32501153        ConstrainSubtypeRelation(lhsWithProxyArgs, rhs, errMsg, false, allowDecisions);
 32501154        ConstrainAssignableTypeArgs(lhs, lhsWithProxyArgs.TypeArgs, lhs.TypeArgs, errMsg, out moreXConstraints);
 59201155        if (lhs.AsCollectionType == null) {
 26701156          var sameHead = Type.SameHead(lhs, rhs);
 26701157          if (!sameHead && lhs is UserDefinedType udtLhs && rhs is UserDefinedType udtRhs) {
 1158            // also allow the case where lhs is a possibly-null type and rhs is a non-null type
 01159            sameHead = udtLhs.ResolvedClass == (udtRhs.ResolvedClass as NonNullTypeDecl)?.Class;
 01160          }
 53201161          if (sameHead) {
 26501162            ConstrainAssignableTypeArgs(lhs, lhs.TypeArgs, rhs.TypeArgs, errMsg, out var more2);
 26501163            moreXConstraints = moreXConstraints || more2;
 26501164          }
 26701165        }
 32501166      }
 5026701167    }
 1168
 3763601169    private void ConstrainAssignableTypeArgs(Type typeHead, List<Type> A, List<Type> B, TypeConstraint.ErrorMsg errMsg, 
 1170      Contract.Requires(typeHead != null);
 1171      Contract.Requires(A != null);
 1172      Contract.Requires(B != null);
 1173      Contract.Requires(A.Count == B.Count);
 1174      Contract.Requires(errMsg != null);
 1175
 3763601176      var tok = errMsg.Tok;
 5837001177      if (B.Count == 0) {
 1178        // all done
 2073401179        moreXConstraints = false;
 3763601180      } else if (typeHead is MapType) {
 01181        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 0 expects {1} <: {0
 01182        AddAssignableConstraint(tok, A[0], B[0], em);
 01183        em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 1 expects {1} <: {0}", 
 01184        AddAssignableConstraint(tok, A[1], B[1], em);
 01185        moreXConstraints = true;
 2092501186      } else if (typeHead is CollectionType) {
 402301187        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter expects {1} <: {0}", A[0], B
 402301188        AddAssignableConstraint(tok, A[0], B[0], em);
 402301189        moreXConstraints = true;
 1690201190      } else {
 1287901191        var udt = (UserDefinedType)typeHead;  // note, collections, maps, and user-defined types are the only one with T
 1287901192        var cl = udt.ResolvedClass;
 1287901193        Contract.Assert(cl != null);
 1287901194        Contract.Assert(cl.TypeArgs.Count == B.Count);
 1287901195        moreXConstraints = false;
 12531601196        for (int i = 0; i < B.Count; i++) {
 3318601197          var msgFormat = "variance for type parameter" + (B.Count == 1 ? "" : " at index " + i) + " expects {0} {1} {2}
 6577201198          if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Co) {
 3258601199            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "co" + msgFormat, A[i], ":>", B[i]);
 3258601200            AddAssignableConstraint(tok, A[i], B[i], em);
 3258601201            moreXConstraints = true;
 3378601202          } else if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Contra) {
 60001203            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "contra" + msgFormat, A[i], "<:", B[i]);
 60001204            AddAssignableConstraint(tok, B[i], A[i], em);
 60001205            moreXConstraints = true;
 60001206          } else {
 01207            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "non" + msgFormat, A[i], "=", B[i]);
 01208            ConstrainSubtypeRelation_Equal(A[i], B[i], em);
 01209          }
 3318601210        }
 1287901211      }
 3763601212    }
 1213
 1214    /// <summary>
 1215    /// Adds the subtyping constraint that "a" and "b" are the same type.
 1216    /// </summary>
 3501217    private void ConstrainSubtypeRelation_Equal(Type a, Type b, TypeConstraint.ErrorMsg errMsg) {
 1218      Contract.Requires(a != null);
 1219      Contract.Requires(b != null);
 1220      Contract.Requires(errMsg != null);
 1221
 3501222      var proxy = a.Normalize() as TypeProxy;
 4101223      if (proxy != null && proxy.T == null && !Reaches(b, proxy, 1, new HashSet<TypeProxy>())) {
 601224        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01225          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, b);
 01226        }
 601227        proxy.T = b;
 601228      }
 3501229      proxy = b.Normalize() as TypeProxy;
 5901230      if (proxy != null && proxy.T == null && !Reaches(a, proxy, 1, new HashSet<TypeProxy>())) {
 2401231        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01232          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, a);
 01233        }
 2401234        proxy.T = a;
 2401235      }
 1236
 3501237      ConstrainSubtypeRelation(a, b, errMsg, true);
 3501238      ConstrainSubtypeRelation(b, a, errMsg, true);
 3501239    }
 1240
 1241    /// <summary>
 1242    /// Adds the subtyping constraint that "sub" is a subtype of "super".
 1243    /// If this constraint seems feasible, returns "true".  Otherwise, prints error message (either "errMsg" or somethin
 1244    /// more specific) and returns "false".
 1245    /// Note, if in doubt, this method can return "true", because the constraints will be checked for sure at a later st
 1246    /// </summary>
 29230901247    private bool ConstrainSubtypeRelation(Type super, Type sub, TypeConstraint.ErrorMsg errMsg, bool keepConstraints = f
 1248      Contract.Requires(sub != null);
 1249      Contract.Requires(super != null);
 1250      Contract.Requires(errMsg != null);
 1251
 34036601252      if (!keepConstraints && super is InferredTypeProxy) {
 4805701253        var ip = (InferredTypeProxy)super;
 8546151254        if (ip.KeepConstraints) {
 3740451255          keepConstraints = true;
 3740451256        }
 4805701257      }
 30610251258      if (!keepConstraints && sub is InferredTypeProxy) {
 1379351259        var ip = (InferredTypeProxy)sub;
 1449751260        if (ip.KeepConstraints) {
 70401261          keepConstraints = true;
 70401262        }
 1379351263      }
 1264
 29230901265      super = super.NormalizeExpand(keepConstraints);
 29230901266      sub = sub.NormalizeExpand(keepConstraints);
 29230901267      var c = new TypeConstraint(super, sub, errMsg, keepConstraints);
 29230901268      AllTypeConstraints.Add(c);
 29230901269      return ConstrainSubtypeRelation_Aux(super, sub, c, keepConstraints, allowDecisions);
 29230901270    }
 29230901271    private bool ConstrainSubtypeRelation_Aux(Type super, Type sub, TypeConstraint c, bool keepConstraints, bool allowDe
 1272      Contract.Requires(sub != null);
 1273      Contract.Requires(!(sub is TypeProxy) || ((TypeProxy)sub).T == null);  // caller is expected to have Normalized aw
 1274      Contract.Requires(super != null);
 1275      Contract.Requires(!(super is TypeProxy) || ((TypeProxy)super).T == null);  // caller is expected to have Normalize
 1276      Contract.Requires(c != null);
 1277
 39429101278      if (object.ReferenceEquals(super, sub)) {
 10198201279        return true;
 26528401280      } else if (super is TypeProxy && sub is TypeProxy) {
 1281        // both are proxies
 7495701282        ((TypeProxy)sub).AddSupertype(c);
 7495701283        ((TypeProxy)super).AddSubtype(c);
 7495701284        return true;
 15045301285      } else if (sub is TypeProxy) {
 3508301286        var proxy = (TypeProxy)sub;
 3508301287        proxy.AddSupertype(c);
 3508301288        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 3508301289        return true;
 12937301290      } else if (super is TypeProxy) {
 4908601291        var proxy = (TypeProxy)super;
 4908601292        proxy.AddSubtype(c);
 4908601293        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 4908601294        return true;
 3120101295      } else {
 1296        // two non-proxy types
 1297        // set "headSymbolsAgree" to "false" if it's clear the head symbols couldn't be the same; "true" means they may 
 3120101298        bool headSymbolsAgree = Type.IsHeadSupertypeOf(super.NormalizeExpand(keepConstraints), sub);
 3120101299        if (!headSymbolsAgree) {
 01300          c.FlagAsError(this);
 01301          return false;
 1302        }
 1303        // TODO: inspect type parameters in order to produce some error messages sooner
 3120101304        return true;
 1305      }
 29230901306    }
 1307
 1308    /// <summary>
 1309    /// "root" says that the type is a non-artificial type (that is, not an ArtificialType) with no proper supertypes.
 1310    /// "leaf" says that the only possible proper subtypes are subset types of the type. Thus, the only
 1311    /// types that are not leaf types are traits and artificial types.
 1312    /// The "headIs" versions speak only about the head symbols, so it is possible that the given
 1313    /// type arguments would change the root/leaf status of the entire type.
 1314    /// </summary>
 10410055001315    void DetermineRootLeaf(Type t, out bool isRoot, out bool isLeaf, out bool headIsRoot, out bool headIsLeaf) {
 1316      Contract.Requires(t != null);
 1317      Contract.Ensures(!Contract.ValueAtReturn(out isRoot) || Contract.ValueAtReturn(out headIsRoot)); // isRoot ==> hea
 1318      Contract.Ensures(!Contract.ValueAtReturn(out isLeaf) || Contract.ValueAtReturn(out headIsLeaf)); // isLeaf ==> hea
 10410055001319      t = t.NormalizeExpandKeepConstraints();
 10410059451320      if (t.IsObjectQ) {
 8901321        isRoot = true; isLeaf = false;
 8901322        headIsRoot = true; headIsLeaf = false;
 10410113701323      } else if (t is ArrowType) {
 58701324        var arr = (ArrowType)t;
 117401325        headIsRoot = true; headIsLeaf = true;  // these are definitely true
 117401326        isRoot = true; isLeaf = true;  // set these to true until proven otherwise
 58701327        Contract.Assert(arr.Arity + 1 == arr.TypeArgs.Count);
 711101328        for (int i = 0; i < arr.TypeArgs.Count; i++) {
 197901329          var arg = arr.TypeArgs[i];
 197901330          DetermineRootLeaf(arg, out var r, out var l, out _, out _);
 337101331          if (i < arr.Arity) {
 278401332            isRoot &= l; isLeaf &= r;  // argument types are contravariant
 197901333          } else {
 117401334            isRoot &= r; isLeaf &= l;  // result type is covariant
 58701335          }
 197901336        }
 10569480901337      } else if (t is UserDefinedType) {
 159430351338        var udt = (UserDefinedType)t;
 159430351339        var cl = udt.ResolvedClass;
 318860701340        if (cl != null) {
 159928751341          if (cl is TypeParameter) {
 498401342            var tp = udt.AsTypeParameter;
 498401343            Contract.Assert(tp != null);
 996801344            headIsRoot = true; headIsLeaf = true;  // all type parameters are non-variant
 212071751345          } else if (cl is SubsetTypeDecl) {
 105282801346            headIsRoot = false; headIsLeaf = true;
 158931951347          } else if (cl is NewtypeDecl) {
 01348            headIsRoot = true; headIsLeaf = true;
 106290551349          } else if (cl is TraitDecl) {
 01350            headIsRoot = false; headIsLeaf = false;
 106295001351          } else if (cl is ClassDecl) {
 8901352            headIsRoot = false; headIsLeaf = true;
 106290551353          } else if (cl is AbstractTypeDecl) {
 01354            headIsRoot = true; headIsLeaf = true;
 106286101355          } else if (cl is InternalTypeSynonymDecl) {
 01356            Contract.Assert(object.ReferenceEquals(t, t.NormalizeExpand())); // should be opaque in scope
 01357            headIsRoot = true; headIsLeaf = true;
 106286101358          } else {
 106286101359            Contract.Assert(cl is DatatypeDecl);
 212572201360            headIsRoot = true; headIsLeaf = true;
 106286101361          }
 1362          // for "isRoot" and "isLeaf", also take into consideration the root/leaf status of type arguments
 318860701363          isRoot = headIsRoot; isLeaf = headIsLeaf;
 159430351364          Contract.Assert(udt.TypeArgs.Count == cl.TypeArgs.Count);
 1602074551365          for (int i = 0; i < udt.TypeArgs.Count; i++) {
 427737951366            var variance = cl.TypeArgs[i].Variance;
 855471451367            if (variance != TypeParameter.TPVariance.Non) {
 427733501368              DetermineRootLeaf(udt.TypeArgs[i], out var r, out var l, out _, out _);
 1369              // isRoot and isLeaf aren't duals, so Co and Contra require separate consideration beyond inversion.
 427733501370              switch (variance) {
 1005623601371                case TypeParameter.TPVariance.Co: { isRoot &= r; isLeaf &= l; break; }
 1372                // A invariably constructible subtype becomes a supertype, and thus the enclosing type is never a root.
 705310401373                case TypeParameter.TPVariance.Contra: { isRoot &= false; isLeaf &= r; break; }
 1374              }
 427733501375            }
 427737951376          }
 159430351377        } else {
 01378          isRoot = false; isLeaf = false;  // don't know
 01379          headIsRoot = false; headIsLeaf = false;
 01380        }
 10743956151381      } else if (t.IsBoolType || t.IsCharType || t.IsIntegerType || t.IsRealType || t.AsNewtype != null || t.IsBitVector
 667928601382        isRoot = true; isLeaf = true;
 667928601383        headIsRoot = true; headIsLeaf = true;
 10250561501384      } else if (t is ArtificialType) {
 01385        isRoot = false; isLeaf = false;
 01386        headIsRoot = false; headIsLeaf = false;
 9916597201387      } else if (t is MapType) {  // map, imap
 01388        Contract.Assert(t.TypeArgs.Count == 2);
 01389        DetermineRootLeaf(t.TypeArgs[0], out var r0, out _, out _, out _);
 01390        DetermineRootLeaf(t.TypeArgs[1], out var r1, out _, out _, out _);
 01391        isRoot = r0 & r1; isLeaf = r0 & r1;  // map types are covariant in both type arguments
 01392        headIsRoot = true; headIsLeaf = true;
 10111057201393      } else if (t is CollectionType) {  // set, iset, multiset, seq
 194460001394        Contract.Assert(t.TypeArgs.Count == 1);
 194460001395        DetermineRootLeaf(t.TypeArgs[0], out isRoot, out isLeaf, out _, out _);  // type is covariant is type argument
 388920001396        headIsRoot = true; headIsLeaf = true;
 9916597201397      } else {
 19444274401398        isRoot = false; isLeaf = false;  // don't know
 19444274401399        headIsRoot = false; headIsLeaf = false;
 9722137201400      }
 10410055001401    }
 1402
 4451403    int _recursionDepth = 0;
 9482301404    private bool AssignProxyAndHandleItsConstraints(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1405      Contract.Requires(proxy != null);
 1406      Contract.Requires(proxy.T == null);
 1407      Contract.Requires(t != null);
 1408      Contract.Requires(!(t is TypeProxy));
 1409      Contract.Requires(!(t is ArtificialType));
 9482301410      if (_recursionDepth == 20000) {
 01411        Contract.Assume(false);  // possible infinite recursion
 01412      }
 9482301413      _recursionDepth++;
 9482301414      var b = AssignProxyAndHandleItsConstraints_aux(proxy, t, keepConstraints);
 9482301415      _recursionDepth--;
 9482301416      return b;
 9482301417    }
 1418    /// <summary>
 1419    /// This method is called if "proxy" is an unassigned proxy and "t" is a type whose head symbol is known.
 1420    /// It always sets "proxy.T" to "t".
 1421    /// Then, it deals with the constraints of "proxy" as follows:
 1422    /// * If the constraint compares "t" with a non-proxy with a head comparable with that of "t",
 1423    ///   then add constraints that the type arguments satisfy the desired subtyping constraint
 1424    /// * If the constraint compares "t" with a non-proxy with a head not comparable with that of "t",
 1425    ///   then report an error
 1426    /// * If the constraint compares "t" with a proxy, then (depending on the constraint and "t") attempt
 1427    ///   to recursively set it
 1428    /// After this process, the proxy's .Supertypes and .Subtypes lists of constraints are no longer needed.
 1429    /// If anything is found to be infeasible, "false" is returned (and the propagation may be interrupted);
 1430    /// otherwise, "true" is returned.
 1431    /// </summary>
 9482301432    private bool AssignProxyAndHandleItsConstraints_aux(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1433      Contract.Requires(proxy != null);
 1434      Contract.Requires(proxy.T == null);
 1435      Contract.Requires(t != null);
 1436      Contract.Requires(!(t is TypeProxy));
 1437      Contract.Requires(!(t is ArtificialType));
 1438
 9482301439      t = keepConstraints ? t.Normalize() : t.NormalizeExpand();
 1440      // never violate the type constraint of a literal expression
 9482301441      var followedRequestedAssignment = true;
 54862601442      foreach (var su in proxy.Supertypes) {
 10211501443        if (su is IntVarietiesSupertype) {
 1054701444          var fam = TypeProxy.GetFamily(t);
 2109401445          if (fam == TypeProxy.Family.IntLike || fam == TypeProxy.Family.BitVector || fam == TypeProxy.Family.Ordinal) {
 1446            // good, let's continue with the request to equate the proxy with t
 1447            // unless...
 1054701448            if (t != t.NormalizeExpand()) {
 1449              // force the type to be a base type
 01450              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01451                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01452              }
 01453              t = t.NormalizeExpand();
 01454              followedRequestedAssignment = false;
 01455            }
 1054701456          } else {
 1457            // hijack the setting of proxy; to do that, we decide on a particular int variety now
 01458            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01459              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Int);
 01460            }
 01461            t = Type.Int;
 01462            followedRequestedAssignment = false;
 01463          }
 1054701464          break;
 8102101465        } else if (su is RealVarietiesSupertype) {
 01466          if (TypeProxy.GetFamily(t) == TypeProxy.Family.RealLike) {
 1467            // good, let's continue with the request to equate the proxy with t
 1468            // unless...
 01469            if (t != t.NormalizeExpand()) {
 1470              // force the type to be a base type
 01471              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01472                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01473              }
 01474              t = t.NormalizeExpand();
 01475              followedRequestedAssignment = false;
 01476            }
 01477          } else {
 1478            // hijack the setting of proxy; to do that, we decide on a particular real variety now
 01479            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01480              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Real)
 01481            }
 01482            t = Type.Real;
 01483            followedRequestedAssignment = false;
 01484          }
 01485          break;
 1486        }
 8102101487      }
 1488      // set proxy.T right away, so that we can freely recurse without having to worry about infinite recursion
 9482301489      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01490        Options.OutputWriter.WriteLine("DEBUG: setting proxy {0}.T := {1}", proxy, t);
 01491      }
 9482301492      proxy.T = t;
 1493
 1494      // check feasibility
 9482301495      DetermineRootLeaf(t, out var isRoot, out var isLeaf, out _, out _);
 1496      // propagate up
 56720401497      foreach (var c in proxy.SupertypeConstraints) {
 9424501498        var u = keepConstraints ? c.Super.NormalizeExpandKeepConstraints() : c.Super.NormalizeExpand();
 17518001499        if (!(u is TypeProxy)) {
 8093501500          ImposeSubtypingConstraint(u, t, c.ErrMsg);
 10440801501        } else if (isRoot) {
 1502          // If t is a root, we might as well constrain u now.  Otherwise, we'll wait until the .Subtype constraint of u
 1016301503          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 1016301504        }
 9424501505      }
 1506      // propagate down
 65138401507      foreach (var c in proxy.SubtypeConstraints) {
 12230501508        var u = keepConstraints ? c.Sub.NormalizeExpandKeepConstraints() : c.Sub.NormalizeExpand();
 12230501509        Contract.Assert(!TypeProxy.IsSupertypeOfLiteral(u));  // these should only appear among .Supertypes
 22163101510        if (!(u is TypeProxy)) {
 9932601511          ImposeSubtypingConstraint(t, u, c.ErrMsg);
 14179401512        } else if (isLeaf) {
 1513          // If t is a leaf (no pun intended), we might as well constrain u now.  Otherwise, we'll wait until the .Super
 1948901514          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 1948901515        }
 12230501516      }
 1517
 9482301518      return followedRequestedAssignment;
 9482301519    }
 1520
 1521    /// <summary>
 1522    /// Impose constraints that "sub" is a subtype of "super", returning "false" if this leads to an overconstrained sit
 1523    /// In most cases, "sub" being a subtype of "super" means that "sub" and "super" have the same head symbol and, ther
 1524    /// same number of type arguments. Depending on the polarities of the type parameters, the corresponding arguments
 1525    /// of "sub" and "super" must be in co-, in-, or contra-variant relationships to each other.
 1526    /// There are two ways "sub" can be a subtype of "super" without the two having the same head symbol.
 1527    /// One way is that "sub" is a subset type. In this case, the method starts by moving "sub" up toward "super".
 1528    /// The other way is that "super" is a trait (possibly
 1529    /// the trait "object").  By a current restriction in Dafny's type system, traits have no type parameters, so in thi
 1530    /// suffices to check that the head symbol of "super" is something that derives from "sub".
 1531    /// </summary>
 22592301532    private bool ImposeSubtypingConstraint(Type super, Type sub, TypeConstraint.ErrorMsg errorMsg) {
 1533      Contract.Requires(super != null && !(super is TypeProxy));
 1534      Contract.Requires(sub != null && !(sub is TypeProxy));
 1535      Contract.Requires(errorMsg != null);
 22592301536      super = super.NormalizeExpandKeepConstraints();
 22592301537      sub = sub.NormalizeExpandKeepConstraints();
 22592301538      List<int> polarities = ConstrainTypeHead_Recursive(super, ref sub);
 22592301539      if (polarities == null) {
 01540        errorMsg.FlagAsError(this);
 01541        return false;
 1542      }
 22592301543      bool keepConstraints = KeepConstraints(super, sub);
 22592301544      var p = polarities.Count;
 22592301545      Contract.Assert(p == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 22592301546      Contract.Assert(p == 0 || sub.TypeArgs.Count == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 88346501547      for (int i = 0; i < p; i++) {
 14387301548        var pol = polarities[i];
 14387301549        var tp = p == 1 ? "" : " " + i;
 14387301550        var errMsg = new TypeConstraint.ErrorMsgWithBase(errorMsg,
 14387301551          pol < 0 ? "contravariant type parameter{0} would require {1} <: {2}" :
 14387301552          pol > 0 ? "covariant type parameter{0} would require {2} <: {1}" :
 14387301553          "non-variant type parameter{0} would require {1} = {2}",
 14387301554          tp, super.TypeArgs[i], sub.TypeArgs[i]);
 28728401555        if (pol >= 0) {
 14341101556          if (!ConstrainSubtypeRelation(super.TypeArgs[i], sub.TypeArgs[i], errMsg, keepConstraints)) {
 01557            return false;
 1558          }
 14341101559        }
 14433501560        if (pol <= 0) {
 46201561          if (!ConstrainSubtypeRelation(sub.TypeArgs[i], super.TypeArgs[i], errMsg, keepConstraints)) {
 01562            return false;
 1563          }
 46201564        }
 14387301565      }
 22592301566      return true;
 22592301567    }
 1568
 1569    /// <summary>
 1570    /// This is a more liberal version of "ConstrainTypeHead" below. It is willing to move "sub"
 1571    /// upward toward its parents until it finds a head that matches "super", if any.
 1572    /// </summary>
 22599701573    private static List<int> ConstrainTypeHead_Recursive(Type super, ref Type sub) {
 1574      Contract.Requires(super != null);
 1575      Contract.Requires(sub != null);
 1576
 22599701577      super = super.NormalizeExpandKeepConstraints();
 22599701578      sub = sub.NormalizeExpandKeepConstraints();
 1579
 22599701580      var polarities = ConstrainTypeHead(super, sub);
 45192001581      if (polarities != null) {
 22592301582        return polarities;
 1583      }
 1584
 37001585      foreach (var subParentType in sub.ParentTypes()) {
 7401586        sub = subParentType;
 7401587        polarities = ConstrainTypeHead_Recursive(super, ref sub);
 14801588        if (polarities != null) {
 7401589          return polarities;
 1590        }
 01591      }
 1592
 01593      return null;
 22599701594    }
 1595
 1596    /// <summary>
 1597    /// Determines if the head of "sub" can be a subtype of "super".
 1598    /// If this is not possible, null is returned.
 1599    /// If it is possible, return a list of polarities, one for each type argument of "sub".  Polarities
 1600    /// indicate:
 1601    ///     +1  co-variant
 1602    ///      0  invariant
 1603    ///     -1  contra-variant
 1604    /// "sub" is of some type that can (in general) have type parameters.
 1605    /// See also note about Dafny's current type system in the description of method "ImposeSubtypingConstraint".
 1606    /// </summary>
 22599701607    private static List<int> ConstrainTypeHead(Type super, Type sub) {
 1608      Contract.Requires(super != null && !(super is TypeProxy));
 1609      Contract.Requires(sub != null && !(sub is TypeProxy));
 24679901610      if (super is IntVarietiesSupertype) {
 2080201611        var famSub = TypeProxy.GetFamily(sub);
 4160401612        if (famSub == TypeProxy.Family.IntLike || famSub == TypeProxy.Family.BitVector || famSub == TypeProxy.Family.Ord
 2080201613          return new List<int>();
 01614        } else {
 01615          return null;
 1616        }
 20519501617      } else if (super is RealVarietiesSupertype) {
 01618        if (TypeProxy.GetFamily(sub) == TypeProxy.Family.RealLike || super.Equals(sub)) {
 01619          return new List<int>();
 01620        } else {
 01621          return null;
 1622        }
 1623      }
 20519501624      switch (TypeProxy.GetFamily(super)) {
 1625        case TypeProxy.Family.Bool:
 1626        case TypeProxy.Family.Char:
 1627        case TypeProxy.Family.IntLike:
 1628        case TypeProxy.Family.RealLike:
 1629        case TypeProxy.Family.Ordinal:
 1630        case TypeProxy.Family.BitVector:
 22662801631          if (super.Equals(sub)) {
 11331401632            if (sub is UserDefinedType subUserDefinedType) {
 01633              return subUserDefinedType.ResolvedClass.TypeArgs.ConvertAll(tp => TypeParameter.Direction(tp.Variance));
 11331401634            } else {
 11331401635              return new List<int>();
 1636            }
 01637          } else {
 01638            return null;
 1639          }
 1640        case TypeProxy.Family.ValueType:
 1641        case TypeProxy.Family.Ref:
 1642        case TypeProxy.Family.Opaque:
 9188101643          break;  // more elaborate work below
 1644        case TypeProxy.Family.Unknown:
 01645          return null;
 1646        default:
 01647          Contract.Assert(false);  // unexpected type (the precondition of ConstrainTypeHead says "no proxies")
 01648          return null;  // please compiler
 1649      }
 10203901650      if (super is SetType) {
 1015801651        var tt = (SetType)super;
 1015801652        var uu = sub as SetType;
 1015801653        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1 } : null;
 9816001654      } else if (super is SeqType) {
 1643701655        return sub is SeqType ? new List<int> { 1 } : null;
 7494101656      } else if (super is MultiSetType) {
 965501657        return sub is MultiSetType ? new List<int> { 1 } : null;
 5563101658      } else if (super is MapType) {
 01659        var tt = (MapType)super;
 01660        var uu = sub as MapType;
 01661        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1, 1 } : null;
 5563101662      } else if (super.IsObjectQ) {
 01663        return sub.IsRefType ? new List<int>() : null;
 5563101664      } else {
 1665        // The only remaining cases are that "super" is a (co)datatype, abstract type, or non-object trait/class.
 1666        // In each of these cases, "super" is a UserDefinedType.
 5563101667        var udfSuper = (UserDefinedType)super;
 5563101668        var clSuper = udfSuper.ResolvedClass;
 5563101669        if (clSuper == null) {
 01670          Contract.Assert(super.TypeArgs.Count == 0);
 01671          if (super.IsTypeParameter) {
 1672            // we're looking at a type parameter
 01673            return super.AsTypeParameter == sub.AsTypeParameter ? new List<int>() : null;
 01674          } else {
 01675            Contract.Assert(super.IsInternalTypeSynonym);
 01676            return super.AsInternalTypeSynonym == sub.AsInternalTypeSynonym ? new List<int>() : null;
 1677          }
 1678        }
 5563101679        var udfSub = sub as UserDefinedType;
 5563101680        var clSub = udfSub == null ? null : udfSub.ResolvedClass;
 5563101681        if (clSub == null) {
 01682          return null;
 11118801683        } else if (clSuper == clSub) {
 1684          // good
 5555701685          var polarities = new List<int>();
 5555701686          Contract.Assert(clSuper.TypeArgs.Count == udfSuper.TypeArgs.Count);
 5555701687          Contract.Assert(clSuper.TypeArgs.Count == udfSub.TypeArgs.Count);
 48954001688          foreach (var tp in clSuper.TypeArgs) {
 10762301689            var polarity = TypeParameter.Direction(tp.Variance);
 10762301690            polarities.Add(polarity);
 10762301691          }
 1692
 5555701693          return polarities;
 7401694        } else if (udfSub.IsRefType && super.IsObjectQ) {
 01695          return new List<int>();
 7401696        } else if (udfSub.IsNonNullRefType && super.IsObject) {
 01697          return new List<int>();
 7401698        } else {
 7401699          return null;
 1700        }
 1701      }
 22599701702    }
 22592301703    private static bool KeepConstraints(Type super, Type sub) {
 1704      Contract.Requires(super != null && !(super is TypeProxy));
 1705      Contract.Requires(sub != null && !(sub is TypeProxy));
 24672501706      if (super is IntVarietiesSupertype) {
 2080201707        return false;
 20512101708      } else if (super is RealVarietiesSupertype) {
 01709        return false;
 1710      }
 20512101711      switch (TypeProxy.GetFamily(super)) {
 1712        case TypeProxy.Family.Bool:
 1713        case TypeProxy.Family.Char:
 1714        case TypeProxy.Family.IntLike:
 1715        case TypeProxy.Family.RealLike:
 1716        case TypeProxy.Family.Ordinal:
 1717        case TypeProxy.Family.BitVector:
 11331401718          return false;
 1719        case TypeProxy.Family.ValueType:
 1720        case TypeProxy.Family.Ref:
 1721        case TypeProxy.Family.Opaque:
 9180701722          break;  // more elaborate work below
 1723        case TypeProxy.Family.Unknown:
 01724          return false;
 1725      }
 12805701726      if (super is SetType || super is SeqType || super is MultiSetType || super is MapType) {
 3625001727        return true;
 5562901728      } else if (super is ArrowType) {
 7201729        return false;
 5548501730      } else if (super.IsObjectQ) {
 01731        return false;
 5548501732      } else {
 1733        // super is UserDefinedType
 5548501734        return true;
 1735      }
 22592301736    }
 1737
 4451738    public List<TypeConstraint> AllTypeConstraints = new List<TypeConstraint>();
 4451739    public List<XConstraint> AllXConstraints = new List<XConstraint>();
 1740
 1741    public class XConstraint {
 1742      public readonly IToken tok;
 1743      public readonly string ConstraintName;
 1744      public readonly Type[] Types;
 1745      public readonly TypeConstraint.ErrorMsg errorMsg;
 26252001746      public XConstraint(IToken tok, string constraintName, Type[] types, TypeConstraint.ErrorMsg errMsg) {
 1747        Contract.Requires(tok != null);
 1748        Contract.Requires(constraintName != null);
 1749        Contract.Requires(types != null);
 1750        Contract.Requires(errMsg != null);
 13126001751        this.tok = tok;
 13126001752        ConstraintName = constraintName;
 13126001753        Types = types;
 13126001754        errorMsg = errMsg;
 13126001755      }
 1756
 01757      public override string ToString() {
 01758        var s = ConstraintName + ":";
 01759        foreach (var t in Types) {
 01760          s += " " + t;
 01761        }
 01762        return s;
 01763      }
 1764
 1765      /// <summary>
 1766      /// Tries to confirm the XConstraint.
 1767      /// If the XConstraint can be confirmed, or at least is plausible enough to have been converted into other type
 1768      /// constraints or more XConstraints, then "true" is returned and the out-parameters "convertedIntoOtherTypeConstr
 1769      /// and "moreXConstraints" are set to true accordingly.
 1770      /// If the XConstraint can be refuted, then an error message will be produced and "true" is returned (to indicate
 1771      /// that this XConstraint has finished serving its purpose).
 1772      /// If there's not enough information to confirm or refute the XConstraint, then "false" is returned.
 1773      /// </summary>
 5877995501774      public bool Confirm(Resolver resolver, bool fullstrength, out bool convertedIntoOtherTypeConstraints, out bool mor
 1775        Contract.Requires(resolver != null);
 5877995501776        convertedIntoOtherTypeConstraints = false;
 5877995501777        moreXConstraints = false;
 5877995501778        var t = Types[0].NormalizeExpand();
 11625989001779        if (t is TypeProxy) {
 5747993501780          switch (ConstraintName) {
 1781            case "Assignable":
 1782            case "Equatable":
 1783            case "EquatableArg":
 1784            case "Indexable":
 1785            case "Innable":
 1786            case "MultiIndexable":
 1787            case "IntOrORDINAL":
 1788              // have a go downstairs
 5389009701789              break;
 1790            default:
 358983801791              return false;  // there's not enough information to confirm or refute this XConstraint
 1792          }
 5389009701793        }
 1794        bool satisfied;
 5519011701795        switch (ConstraintName) {
 5500777301796          case "Assignable": {
 5500777301797              Contract.Assert(t == t.Normalize());  // it's already been normalized above
 5500777301798              var u = Types[1].NormalizeExpand();
 5500777301799              if (CheckTypeInferenceVisitor.IsDetermined(t) &&
 5500777301800                  (fullstrength
 5500777301801                   || !ProxyWithNoSubTypeConstraint(u, resolver)
 5500777301802                   || (u is TypeProxy
 5500777301803                       && Types[0].NormalizeExpandKeepConstraints() is var t0constrained
 5500777301804                       && (t0constrained.IsNonNullRefType || t0constrained.AsSubsetType != null)
 5505804001805                       && resolver.HasApplicableNullableRefTypeConstraint(new HashSet<TypeProxy>() { (TypeProxy)u })))) 
 1806                // This is the best case.  We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 5026701807                if (CheckTypeInferenceVisitor.IsDetermined(u) && t.IsSubtypeOf(u, false, true) && t.IsRefType) {
 1808                  // But we also allow cases where the rhs is a proper supertype of the lhs, and let the verifier
 1809                  // determine whether the rhs is provably an instance of the lhs.
 01810                  resolver.ConstrainAssignable((NonProxyType)u, (NonProxyType)t, errorMsg, out moreXConstraints, fullstr
 5026701811                } else {
 5026701812                  resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 5026701813                }
 5026701814                convertedIntoOtherTypeConstraints = true;
 5026701815                return true;
 5495750601816              } else if (u.IsTypeParameter) {
 1817                // we need the constraint base(t) :> u, which for a type parameter t can happen iff t :> u
 01818                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 01819                convertedIntoOtherTypeConstraints = true;
 01820                return true;
 5499455201821              } else if (Type.FromSameHead(t, u, out var tUp, out var uUp)) {
 3704601822                resolver.ConstrainAssignableTypeArgs(tUp, tUp.TypeArgs, uUp.TypeArgs, errorMsg, out moreXConstraints);
 3704601823                return true;
 5492046001824              } else if (fullstrength && t is NonProxyType) {
 1825                // We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 01826                resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 01827                convertedIntoOtherTypeConstraints = true;
 01828                return true;
 5492046001829              } else if (fullstrength && u is NonProxyType) {
 1830                // We're willing to change "base(t) :> u" to the stronger constraint "t :> u" for the sake of making pro
 01831                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 01832                convertedIntoOtherTypeConstraints = true;
 01833                return true;
 1834              }
 1835              // There's not enough information to say anything
 5492046001836              return false;
 1837            }
 1838          case "NumericType":
 01839            satisfied = t.IsNumericBased();
 01840            break;
 1841          case "IntegerType":
 3401842            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 3401843            break;
 1844          case "IsBitvector":
 01845            satisfied = t.IsBitVectorType;
 01846            break;
 1847          case "IsRefType":
 01848            satisfied = t.IsRefType;
 01849            break;
 1850          case "IsNullableRefType":
 8901851            satisfied = t.IsRefType && !t.IsNonNullRefType;
 8901852            break;
 1853          case "Orderable_Lt":
 235601854            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 235601855            break;
 1856          case "Orderable_Gt":
 13101857            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 13101858            break;
 01859          case "RankOrderable": {
 01860              var u = Types[1].NormalizeExpand();
 01861              if (u is TypeProxy) {
 01862                return false;  // not enough information
 1863              }
 01864              satisfied = (t.IsIndDatatype || t.IsTypeParameter) && u.IsIndDatatype;
 01865              break;
 1866            }
 1867          case "Plussable":
 137501868            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 137501869            break;
 1870          case "Minusable":
 13401871            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 13401872            break;
 1873          case "Mullable":
 7701874            satisfied = t.IsNumericBased() || t.IsBitVectorType || t is SetType || t is MultiSetType;
 7701875            break;
 1876          case "IntOrORDINAL":
 01877            if (!(t is TypeProxy)) {
 01878              if (TernaryExpr.PrefixEqUsesNat) {
 01879                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 01880              } else {
 01881                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBigOrdinalType;
 01882              }
 01883            } else if (fullstrength) {
 01884              var proxy = (TypeProxy)t;
 01885              if (TernaryExpr.PrefixEqUsesNat) {
 01886                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.Int);
 01887              } else {
 1888                // let's choose ORDINAL over int
 01889                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.BigOrdinal);
 01890              }
 01891              convertedIntoOtherTypeConstraints = true;
 01892              satisfied = true;
 01893            } else {
 01894              return false;
 1895            }
 01896            break;
 1897          case "NumericOrBitvector":
 376701898            satisfied = t.IsNumericBased() || t.IsBitVectorType;
 376701899            break;
 1900          case "NumericOrBitvectorOrCharOrORDINAL":
 9301901            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsCharType || t.IsBigOrdinalType;
 9301902            break;
 1903          case "IntLikeOrBitvector":
 8901904            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBitVectorType;
 8901905            break;
 1906          case "BooleanBits":
 2601907            satisfied = t.IsBoolType || t.IsBitVectorType;
 2601908            break;
 1909          case "Sizeable":
 95001910            satisfied = (t is SetType && ((SetType)t).Finite) || t is MultiSetType || t is SeqType || (t is MapType && (
 95001911            break;
 1912          case "Disjointable":
 11501913            satisfied = t is SetType || t is MultiSetType;
 11501914            break;
 1915          case "MultiSetConvertible":
 3301916            satisfied = (t is SetType && ((SetType)t).Finite) || t is SeqType;
 6601917            if (satisfied) {
 3301918              Type elementType = ((CollectionType)t).Arg;
 3301919              var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 3301920              var em = new TypeConstraint.ErrorMsgWithBase(errorMsg, "expecting element type {0} (got {1})", u, elementT
 3301921              resolver.ConstrainSubtypeRelation_Equal(elementType, u, em);
 3301922              convertedIntoOtherTypeConstraints = true;
 3301923            }
 3301924            break;
 1925          case "IsCoDatatype":
 01926            satisfied = t.IsCoDatatype;
 01927            break;
 1928          case "Indexable":
 22901929            if (!(t is TypeProxy)) {
 9701930              satisfied = t is SeqType || t is MultiSetType || t is MapType || (t.IsArrayType && t.AsArrayType.Dims == 1
 13201931            } else {
 1932              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1933              // that it does have the form "array<?>", since "object" would not be Indexable.
 3501934              var proxy = (TypeProxy)t;
 3501935              Type join = null;
 7001936              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 3501937                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 3501938                var tt = headWithProxyArgs.NormalizeExpand();
 3501939                satisfied = tt is SeqType || tt is MultiSetType || tt is MapType || (tt.IsArrayType && tt.AsArrayType.Di
 7001940                if (satisfied) {
 3501941                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 3501942                  convertedIntoOtherTypeConstraints = true;
 3501943                }
 3501944              } else {
 01945                return false;  // we can't determine the answer
 1946              }
 3501947            }
 13201948            break;
 1949          case "MultiIndexable":
 249201950            if (!(t is TypeProxy)) {
 124601951              satisfied = t is SeqType || (t.IsArrayType && t.AsArrayType.Dims == 1);
 124601952            } else {
 1953              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1954              // that it does have the form "array<?>", since "object" would not be Indexable.
 01955              var proxy = (TypeProxy)t;
 01956              Type join = null;
 01957              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 01958                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 01959                var tt = headWithProxyArgs.NormalizeExpand();
 01960                satisfied = tt is SeqType || (tt.IsArrayType && tt.AsArrayType.Dims == 1);
 01961                if (satisfied) {
 01962                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 01963                  convertedIntoOtherTypeConstraints = true;
 01964                }
 01965              } else {
 01966                return false;  // we can't determine the answer
 1967              }
 01968            }
 124601969            break;
 5923101970          case "Innable": {
 5923101971              var elementType = FindCollectionType(resolver.Options, t, true, new HashSet<TypeProxy>()) ?? FindCollectio
 5938601972              if (elementType != null) {
 15501973                var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 15501974                resolver.AddXConstraint(this.tok, "Equatable", elementType, u, new TypeConstraint.ErrorMsgWithBase(error
 15501975                moreXConstraints = true;
 15501976                return true;
 1977              }
 11815201978              if (t is TypeProxy) {
 5907601979                return false;  // not enough information to do anything
 1980              }
 01981              satisfied = false;
 01982              break;
 1983            }
 12301984          case "SeqUpdatable": {
 12301985              var xcWithExprs = (XConstraintWithExprs)this;
 12301986              var index = xcWithExprs.Exprs[0];
 12301987              var value = xcWithExprs.Exprs[1];
 21201988              if (t is SeqType) {
 8901989                var s = (SeqType)t;
 8901990                resolver.ConstrainToIntegerType(index, true, "sequence update requires integer- or bitvector-based index
 8901991                resolver.ConstrainSubtypeRelation(s.Arg, value.Type, value, "sequence update requires the value to have 
 12301992              } else if (t is MapType) {
 01993                var s = (MapType)t;
 01994                if (s.Finite) {
 01995                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "map update requires domain element to 
 01996                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "map update requires the value to have t
 01997                } else {
 01998                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "imap update requires domain element to
 01999                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "imap update requires the value to have 
 02000                }
 6802001              } else if (t is MultiSetType) {
 3402002                var s = (MultiSetType)t;
 3402003                resolver.ConstrainSubtypeRelation(s.Arg, index.Type, index, "multiset update requires domain element to 
 3402004                resolver.ConstrainToIntegerType(value, false, "multiset update requires integer-based numeric value (got
 3402005              } else {
 02006                satisfied = false;
 02007                break;
 2008              }
 12302009              convertedIntoOtherTypeConstraints = true;
 12302010              return true;
 2011            }
 2012          case "ContainerIndex":
 2013            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then its element/domai
 2014            Type indexType;
 378102015            if (t is SeqType || t.IsArrayType) {
 186902016              resolver.ConstrainToIntegerType(errorMsg.Tok, Types[1], true, errorMsg);
 186902017              convertedIntoOtherTypeConstraints = true;
 186902018              return true;
 4302019            } else if (t is MapType) {
 02020              indexType = ((MapType)t).Domain;
 8602021            } else if (t is MultiSetType) {
 4302022              indexType = ((MultiSetType)t).Arg;
 4302023            } else {
 2024              // some other head symbol; that's cool
 02025              return true;
 2026            }
 2027            // note, it's okay if "Types[1]" is a TypeProxy
 4302028            resolver.ConstrainSubtypeRelation(indexType, Types[1], errorMsg);  // use the same error message
 4302029            convertedIntoOtherTypeConstraints = true;
 4302030            return true;
 2031          case "ContainerResult":
 2032            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then the type of a sel
 2033            Type resultType;
 271302034            if (t is SeqType) {
 133502035              resultType = ((SeqType)t).Arg;
 137802036            } else if (t.IsArrayType) {
 02037              resultType = UserDefinedType.ArrayElementType(t);
 4302038            } else if (t is MapType) {
 02039              resultType = ((MapType)t).Range;
 8602040            } else if (t is MultiSetType) {
 4302041              resultType = resolver.builtIns.Nat();
 4302042            } else {
 2043              // some other head symbol; that's cool
 02044              return true;
 2045            }
 2046            // note, it's okay if "Types[1]" is a TypeProxy
 137802047            resolver.ConstrainSubtypeRelation(Types[1], resultType, errorMsg);
 137802048            convertedIntoOtherTypeConstraints = true;
 137802049            return true;
 7716402050          case "Equatable": {
 7716402051              t = Types[0].NormalizeExpandKeepConstraints();
 7716402052              var u = Types[1].NormalizeExpandKeepConstraints();
 7725902053              if (object.ReferenceEquals(t, u)) {
 9502054                return true;
 2055              }
 10453702056              if (t is TypeProxy && u is TypeProxy) {
 2746802057                return false;  // not enough information to do anything sensible
 9905802058              } else if (t is TypeProxy || u is TypeProxy) {
 2059                TypeProxy proxy;
 2060                Type other;
 7521602061                if (t is TypeProxy) {
 2575902062                  proxy = (TypeProxy)t;
 2575902063                  other = u;
 4945702064                } else {
 2369802065                  proxy = (TypeProxy)u;
 2369802066                  other = t;
 2369802067                }
 4956202068                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 10502069                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 10502070                  convertedIntoOtherTypeConstraints = true;
 10502071                  return true;
 4944102072                } else if (fullstrength) {
 2073                  // the following is rather aggressive
 8902074                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02075                    return false;
 8902076                  } else {
 17802077                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 8902078                      other = other.NormalizeExpand();  // shave off all constraints
 8902079                    }
 8902080                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 8902081                    convertedIntoOtherTypeConstraints = true;
 8902082                    break;
 2083                  }
 4926302084                } else {
 4926302085                  return false;  // not enough information
 2086                }
 2087              }
 2088
 14402089              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 28802090              if (satisfied) {
 14402091                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 14402092                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 68102093                for (int i = 0; i < a.TypeArgs.Count; i++) {
 13102094                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 13102095                    a.TypeArgs[i], b.TypeArgs[i],
 13102096                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 13102097                    a.IsRefType,
 13102098                    errorMsg));
 13102099                  moreXConstraints = true;
 13102100                }
 14402101              }
 14402102              break;
 2103            }
 3188902104          case "EquatableArg": {
 3188902105              t = Types[0].NormalizeExpandKeepConstraints();
 3188902106              var u = Types[1].NormalizeExpandKeepConstraints();
 3188902107              var moreExactThis = (XConstraint_EquatableArg)this;
 5122402108              if (t is TypeProxy && u is TypeProxy) {
 1933502109                return false;  // not enough information to do anything sensible
 2489502110              } else if (t is TypeProxy || u is TypeProxy) {
 2111                TypeProxy proxy;
 2112                Type other;
 1532802113                if (t is TypeProxy) {
 298702114                  proxy = (TypeProxy)t;
 298702115                  other = u;
 1234102116                } else {
 935402117                  proxy = (TypeProxy)u;
 935402118                  other = t;
 935402119                }
 1236602120                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 2502121                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 2502122                  convertedIntoOtherTypeConstraints = true;
 2502123                  return true;
 1231602124                } else if (fullstrength) {
 2125                  // the following is rather aggressive
 02126                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02127                    return false;
 02128                  } else {
 02129                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 02130                      other = other.NormalizeExpand();  // shave off all constraints
 02131                    }
 02132                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 02133                    convertedIntoOtherTypeConstraints = true;
 02134                    break;
 2135                  }
 1231602136                } else {
 1231602137                  return false;  // not enough information
 2138                }
 2139              }
 21302140              if (moreExactThis.TreatTypeParamAsWild && (t.IsTypeParameter || u.IsTypeParameter || t.IsAbstractType || u
 02141                return true;
 21302142              } else if (!moreExactThis.AllowSuperSub) {
 02143                resolver.ConstrainSubtypeRelation_Equal(t, u, errorMsg);
 02144                convertedIntoOtherTypeConstraints = true;
 02145                return true;
 2146              }
 2147
 2148              // okay if t<:u or u<:t (this makes type inference more manageable, though it is more liberal than one mig
 21302149              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 42602150              if (satisfied) {
 21302151                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 21302152                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 74702153                for (int i = 0; i < a.TypeArgs.Count; i++) {
 10702154                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 10702155                    a.TypeArgs[i], b.TypeArgs[i],
 10702156                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 10702157                    false,
 10702158                    errorMsg));
 10702159                  moreXConstraints = true;
 10702160                }
 21302161              }
 21302162              break;
 2163            }
 02164          case "Freshable": {
 02165              var collType = t.AsCollectionType;
 02166              if (collType is SetType || collType is SeqType) {
 02167                t = collType.Arg.NormalizeExpand();
 02168              }
 02169              if (t is TypeProxy) {
 02170                return false;  // there is not enough information
 2171              }
 02172              satisfied = t.IsRefType;
 02173              break;
 2174            }
 02175          case "ModifiesFrame": {
 02176              var u = Types[1].NormalizeExpand();  // eventual ref type
 02177              var collType = t is MapType ? null : t.AsCollectionType;
 02178              if (collType != null) {
 02179                t = collType.Arg.NormalizeExpand();
 02180              }
 02181              if (t is TypeProxy) {
 02182                if (collType != null) {
 2183                  // we know enough to convert into a subtyping constraint
 02184                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02185                  moreXConstraints = true;
 02186                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02187                  moreXConstraints = true;
 02188                  convertedIntoOtherTypeConstraints = true;
 02189                  return true;
 02190                } else {
 02191                  return false;  // there is not enough information
 2192                }
 2193              }
 02194              if (t.IsRefType) {
 02195                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02196                convertedIntoOtherTypeConstraints = true;
 02197                return true;
 2198              }
 02199              satisfied = false;
 02200              break;
 2201            }
 02202          case "ReadsFrame": {
 02203              var u = Types[1].NormalizeExpand();  // eventual ref type
 02204              var arrTy = t.AsArrowType;
 02205              if (arrTy != null) {
 02206                t = arrTy.Result.NormalizeExpand();
 02207              }
 02208              var collType = t is MapType ? null : t.AsCollectionType;
 02209              if (collType != null) {
 02210                t = collType.Arg.NormalizeExpand();
 02211              }
 02212              if (t is TypeProxy) {
 02213                if (collType != null) {
 2214                  // we know enough to convert into a subtyping constraint
 02215                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02216                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02217                  moreXConstraints = true;
 02218                  convertedIntoOtherTypeConstraints = true;
 02219                  return true;
 02220                } else {
 02221                  return false;  // there is not enough information
 2222                }
 2223              }
 02224              if (t.IsRefType && (arrTy == null || collType != null)) {
 02225                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02226                convertedIntoOtherTypeConstraints = true;
 02227                return true;
 2228              }
 02229              satisfied = false;
 02230              break;
 2231            }
 2232          default:
 02233            Contract.Assume(false);  // unknown XConstraint
 02234            return false;  // to please the compiler
 2235        }
 1109302236        if (!satisfied) {
 02237          errorMsg.FlagAsError(resolver);
 02238        }
 1109302239        return true;  // the XConstraint has served its purpose
 5877995502240      }
 2241
 88631002242      public bool ProxyWithNoSubTypeConstraint(Type u, Resolver resolver) {
 2243        Contract.Requires(u != null);
 2244        Contract.Requires(resolver != null);
 88631002245        var proxy = u as TypeProxy;
 172776302246        if (proxy != null) {
 84155302247          if (proxy.SubtypeConstraints.Any()) {
 10002248            return false;
 2249          }
 9846938082250          foreach (var xc in resolver.AllXConstraints) {
 -11117672262251            if (xc.ConstraintName == "Assignable" && xc.Types[0] == proxy) {
 531002252              return false;
 2253            }
 -11118734262254          }
 83604302255          return true;
 2256        }
 4485702257        return false;
 88631002258      }
 2259
 02260      internal bool CouldBeAnything() {
 02261        return Types.All(t => t.NormalizeExpand() is TypeProxy);
 02262      }
 2263
 2264      /// <summary>
 2265      /// If "t" or any type among its transitive sub/super-types (depending on "towardsSub")
 2266      /// is a collection type, then returns the element/domain type of that collection.
 2267      /// Otherwise, returns null.
 2268      /// </summary>
 18580802269      Type FindCollectionType(DafnyOptions options, Type t, bool towardsSub, ISet<TypeProxy> visited) {
 2270        Contract.Requires(t != null);
 2271        Contract.Requires(visited != null);
 18580802272        t = t.NormalizeExpand();
 18580802273        if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02274          options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}, {1})", t, towardsSub ? "sub" : "super");
 02275        }
 18596302276        if (t is CollectionType) {
 15502277          if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02278            options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}) = {1}", t, ((CollectionType)t).Arg);
 02279          }
 15502280          return ((CollectionType)t).Arg;
 2281        }
 18565302282        var proxy = t as TypeProxy;
 22199202283        if (proxy == null || visited.Contains(proxy)) {
 3633902284          return null;
 2285        }
 14931402286        visited.Add(proxy);
 65036902287        foreach (var sub in towardsSub ? proxy.Subtypes : proxy.Supertypes) {
 6748202288          var e = FindCollectionType(options, sub, towardsSub, visited);
 6750102289          if (e != null) {
 1902290            return e;
 2291          }
 6746302292        }
 14929502293        return null;
 18580802294      }
 2295    }
 2296
 2297    public class XConstraintWithExprs : XConstraint {
 2298      public readonly Expression[] Exprs;
 2299      public XConstraintWithExprs(IToken tok, string constraintName, Type[] types, Expression[] exprs, TypeConstraint.Er
 24602300        : base(tok, constraintName, types, errMsg) {
 2301        Contract.Requires(tok != null);
 2302        Contract.Requires(constraintName != null);
 2303        Contract.Requires(types != null);
 2304        Contract.Requires(exprs != null);
 2305        Contract.Requires(errMsg != null);
 12302306        this.Exprs = exprs;
 12302307      }
 2308    }
 2309
 2310    public class XConstraint_EquatableArg : XConstraint {
 2311      public bool AllowSuperSub;
 2312      public bool TreatTypeParamAsWild;
 2313      public XConstraint_EquatableArg(IToken tok, Type a, Type b, bool allowSuperSub, bool treatTypeParamAsWild, TypeCon
 47602314        : base(tok, "EquatableArg", new Type[] { a, b }, errMsg) {
 2315        Contract.Requires(tok != null);
 2316        Contract.Requires(a != null);
 2317        Contract.Requires(b != null);
 2318        Contract.Requires(errMsg != null);
 23802319        AllowSuperSub = allowSuperSub;
 23802320        TreatTypeParamAsWild = treatTypeParamAsWild;
 23802321      }
 2322    }
 2323
 2324    /// <summary>
 2325    /// Solves or simplifies as many type constraints as possible.
 2326    /// If "allowDecisions" is "false", then no decisions, only determined inferences, are made; this mode is
 2327    /// appropriate for the partial solving that's done before a member lookup.
 2328    /// </summary>
 1157252329    public void PartiallySolveTypeConstraints(bool allowDecisions) {
 1157252330      int state = 0;
 38711502331      while (true) {
 19701152332        if (2 <= state && !allowDecisions) {
 2333          // time to say goodnight to Napoli
 345402334          return;
 19822202335        } else if (AllTypeConstraints.Count == 0 && AllXConstraints.Count == 0) {
 2336          // we're done
 811852337          return;
 2338        }
 2339
 18198502340        var anyNewConstraints = false;
 18198502341        var fullStrength = false;
 2342        // Process subtyping constraints
 18198502343        PrintTypeConstraintState(220 + 2 * state);
 18198502344        switch (state) {
 8116202345          case 0: {
 8116202346              var allTypeConstraints = AllTypeConstraints;
 8116202347              AllTypeConstraints = new List<TypeConstraint>();
 8116202348              var processed = new HashSet<TypeConstraint>();
 11995938002349              foreach (var c in allTypeConstraints) {
 3990529802350                ProcessOneSubtypingConstraintAndItsSubs(c, processed, fullStrength, ref anyNewConstraints);
 3990529802351              }
 2352
 8116202353              allTypeConstraints = new List<TypeConstraint>(AllTypeConstraints);  // copy the list
 11933401502354              foreach (var c in allTypeConstraints) {
 3969684302355                var super = c.Super.NormalizeExpand() as TypeProxy;
 3970025302356                if (AssignKnownEnd(super, true, fullStrength)) {
 341002357                  anyNewConstraints = true;
 3969684302358                } else if (super != null && fullStrength && AssignKnownEndsFullstrength(super)) {  // KRML: is this used
 02359                  anyNewConstraints = true;
 02360                }
 3969684302361              }
 8116202362            }
 8116202363            break;
 2364
 6414302365          case 1: {
 2366              // Process XConstraints
 2367              // confirm as many XConstraints as possible, setting "anyNewConstraints" to "true" if the confirmation
 2368              // of an XConstraint gives rise to new constraints to be handled in the loop above
 2369              bool generatedMoreXConstraints;
 9161802370              do {
 9161802371                generatedMoreXConstraints = false;
 9161802372                var allXConstraints = AllXConstraints;
 9161802373                AllXConstraints = new List<XConstraint>();
 17661445202374                foreach (var xc in allXConstraints) {
 5888197602375                  if (xc.Confirm(this, fullStrength, out var convertedIntoOtherTypeConstraints, out var moreXConstraints
 15598802376                    if (convertedIntoOtherTypeConstraints) {
 5387802377                      anyNewConstraints = true;
 10211002378                    } else {
 4823202379                      generatedMoreXConstraints = true;
 4823202380                    }
 11906602381                    if (moreXConstraints) {
 1695602382                      generatedMoreXConstraints = true;
 1695602383                    }
 5877986602384                  } else {
 5867775602385                    AllXConstraints.Add(xc);
 5867775602386                  }
 5877986602387                }
 18323602388              } while (generatedMoreXConstraints);
 6414302389            }
 6414302390            break;
 2391
 3220402392          case 2: {
 2035648102393              var assignables = AllXConstraints.Where(xc => xc.ConstraintName == "Assignable").ToList();
 3220402394              var postponeForNow = new HashSet<TypeProxy>();
 5117185502395              foreach (var constraint in AllTypeConstraints) {
 1702508102396                var lhs = constraint.Super.NormalizeExpandKeepConstraints() as NonProxyType;
 2181085402397                if (lhs != null) {
 2741914802398                  foreach (var ta in lhs.TypeArgs) {
 435394302399                    AddAllProxies(ta, postponeForNow);
 435394302400                  }
 478577302401                }
 1702508102402              }
 5117185502403              foreach (var constraint in AllTypeConstraints) {
 1702508102404                var lhs = constraint.Super.Normalize() as TypeProxy;
 2428075102405                if (lhs != null && !postponeForNow.Contains(lhs)) {
 7812361302406                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 725627402407                  if (ProcessAssignable(lhs, rhss)) {
 60402408                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 60402409                  }
 725567002410                }
 1702508102411              }
 2170773902412              foreach (var assignable in assignables) {
 721361302413                var lhs = assignable.Types[0].Normalize() as TypeProxy;
 1417194302414                if (lhs != null && !postponeForNow.Contains(lhs)) {
 -19008426342415                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 698804202416                  if (ProcessAssignable(lhs, rhss)) {
 2971202417                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 2418                                               // process only one Assignable constraint in this way
 2971202419                    break;
 2420                  }
 692861802421                }
 718390102422              }
 3220402423            }
 3220402424            break;
 2425
 2426          case 3:
 239702427            anyNewConstraints = ConvertAssignableToSubtypeConstraints(null);
 239702428            break;
 2429
 157602430          case 4: {
 157602431              var allTC = AllTypeConstraints;
 157602432              AllTypeConstraints = new List<TypeConstraint>();
 157602433              var proxyProcessed = new HashSet<TypeProxy>();
 22153202434              foreach (var c in allTC) {
 7226802435                ProcessFullStrength_SubDirection(c.Super, proxyProcessed, ref anyNewConstraints);
 7226802436              }
 9225002437              foreach (var xc in AllXConstraints) {
 4953602438                if (xc.ConstraintName == "Assignable") {
 2036202439                  ProcessFullStrength_SubDirection(xc.Types[0], proxyProcessed, ref anyNewConstraints);
 2036202440                }
 2917402441              }
 311502442              if (!anyNewConstraints) {
 2443                // only do super-direction if sub-direction had no effect
 153902444                proxyProcessed = new HashSet<TypeProxy>();
 18102302445                foreach (var c in allTC) {
 5880202446                  ProcessFullStrength_SuperDirection(c.Sub, proxyProcessed, ref anyNewConstraints);
 5880202447                }
 7701902448                foreach (var xc in AllXConstraints) {
 4083702449                  if (xc.ConstraintName == "Assignable") {
 1670302450                    ProcessFullStrength_SuperDirection(xc.Types[1], proxyProcessed, ref anyNewConstraints);
 1670302451                  }
 2413402452                }
 153902453              }
 157602454              AllTypeConstraints.AddRange(allTC);
 157602455            }
 157602456            break;
 2457
 41402458          case 5: {
 2459              // Process default numeric types
 41402460              var allTypeConstraints = AllTypeConstraints;
 41402461              AllTypeConstraints = new List<TypeConstraint>();
 2943902462              foreach (var c in allTypeConstraints) {
 1172602463                if (c.Super is ArtificialType) {
 232702464                  var proxy = c.Sub.NormalizeExpand() as TypeProxy;
 461102465                  if (proxy != null) {
 228402466                    AssignProxyAndHandleItsConstraints(proxy, c.Super is IntVarietiesSupertype ? (Type)Type.Int : Type.R
 228402467                    anyNewConstraints = true;
 228402468                    continue;
 2469                  }
 4302470                }
 711502471                AllTypeConstraints.Add(c);
 711502472              }
 41402473            }
 41402474            break;
 2475
 8902476          case 6: {
 8902477              fullStrength = true;
 2478              bool generatedMoreXConstraints;
 8902479              do {
 8902480                generatedMoreXConstraints = false;
 8902481                var allXConstraints = AllXConstraints;
 8902482                AllXConstraints = new List<XConstraint>();
 80102483                foreach (var xc in allXConstraints) {
 26702484                  if ((xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") && xc.Confirm(this, full
 17802485                    if (convertedIntoOtherTypeConstraints) {
 8902486                      anyNewConstraints = true;
 8902487                    } else {
 02488                      generatedMoreXConstraints = true;
 02489                    }
 8902490                    if (moreXConstraints) {
 02491                      generatedMoreXConstraints = true;
 02492                    }
 17802493                  } else {
 8902494                    AllXConstraints.Add(xc);
 8902495                  }
 17802496                }
 17802497              } while (generatedMoreXConstraints);
 8902498            }
 8902499            break;
 2500
 02501          case 7: {
 2502              // Process default reference types
 02503              var allXConstraints = AllXConstraints;
 02504              AllXConstraints = new List<XConstraint>();
 02505              foreach (var xc in allXConstraints) {
 02506                if (xc.ConstraintName == "IsRefType" || xc.ConstraintName == "IsNullableRefType") {
 02507                  var proxy = xc.Types[0].Normalize() as TypeProxy;  // before we started processing default types, this
 02508                  if (proxy != null) {
 02509                    AssignProxyAndHandleItsConstraints(proxy, builtIns.ObjectQ());
 02510                    anyNewConstraints = true;
 02511                    continue;
 2512                  }
 02513                }
 02514                AllXConstraints.Add(xc);
 02515              }
 02516            }
 02517            break;
 2518
 02519          case 8: fullStrength = true; goto case 0;
 02520          case 9: fullStrength = true; goto case 1;
 2521
 02522          case 10: {
 2523              // Finally, collapse constraints involving only proxies, which will have the effect of trading some type e
 2524              // messages for type-underspecification messages.
 02525              var allTypeConstraints = AllTypeConstraints;
 02526              AllTypeConstraints = new List<TypeConstraint>();
 02527              foreach (var c in allTypeConstraints) {
 02528                var super = c.Super.NormalizeExpand();
 02529                var sub = c.Sub.NormalizeExpand();
 02530                if (super == sub) {
 02531                  continue;
 02532                } else if (super is TypeProxy && sub is TypeProxy) {
 02533                  var proxy = (TypeProxy)super;
 02534                  if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02535                    Options.OutputWriter.WriteLine("DEBUG: (merge in PartiallySolve) assigning proxy {0}.T := {1}", prox
 02536                  }
 02537                  proxy.T = sub;
 02538                  anyNewConstraints = true;  // signal a change in the constraints
 02539                  continue;
 2540                }
 02541                AllTypeConstraints.Add(c);
 02542              }
 02543            }
 02544            break;
 2545
 02546          case 11: {
 2547              // Last resort decisions. Sometimes get here even with some 'obvious'
 2548              // inferences. Before this case was added, the type inference returned with
 2549              // failure, so this is a conservative addition, and could be made more
 2550              // capable.
 02551              if (!allowDecisions) {
 02552                break;
 2553              }
 2554
 02555              foreach (var c in AllXConstraints) {
 02556                if (c.ConstraintName == "EquatableArg") {
 02557                  ConstrainSubtypeRelation_Equal(c.Types[0], c.Types[1], c.errorMsg);
 02558                  anyNewConstraints = true;
 02559                  AllXConstraints.Remove(c);
 02560                  break;
 2561                }
 02562              }
 02563              if (anyNewConstraints) {
 02564                break;
 2565              }
 2566
 02567              TypeConstraint.ErrorMsg oneSuperErrorMsg = null;
 02568              TypeConstraint.ErrorMsg oneSubErrorMsg = null;
 02569              var ss = new HashSet<Type>();
 02570              foreach (var c in AllTypeConstraints) {
 02571                var super = c.Super.NormalizeExpand();
 02572                var sub = c.Sub.NormalizeExpand();
 02573                if (super is TypeProxy && !ss.Contains(super)) {
 02574                  ss.Add(super);
 02575                }
 02576                if (sub is TypeProxy && !ss.Contains(sub)) {
 02577                  ss.Add(sub);
 02578                }
 02579              }
 2580
 02581              foreach (var t in ss) {
 02582                var lowers = new HashSet<Type>();
 02583                var uppers = new HashSet<Type>();
 02584                foreach (var c in AllTypeConstraints) {
 02585                  var super = c.Super.NormalizeExpand();
 02586                  var sub = c.Sub.NormalizeExpand();
 02587                  if (t.Equals(super)) {
 02588                    lowers.Add(sub);
 02589                    oneSubErrorMsg = c.ErrMsg;
 02590                  }
 02591                  if (t.Equals(sub)) {
 02592                    uppers.Add(super);
 02593                    oneSuperErrorMsg = c.ErrMsg;
 02594                  }
 02595                }
 2596
 02597                bool done = false;
 02598                foreach (var tl in lowers) {
 02599                  foreach (var tu in uppers) {
 02600                    if (tl.Equals(tu)) {
 02601                      if (!ContainsAsTypeParameter(tu, t)) {
 02602                        var errorMsg = new TypeConstraint.ErrorMsgWithBase(AllTypeConstraints[0].ErrMsg,
 02603                          "Decision: {0} is decided to be {1} because the latter is both the upper and lower bound to th
 02604                          t, tu);
 02605                        ConstrainSubtypeRelation_Equal(t, tu, errorMsg);
 2606                        // The above changes t so that it is a proxy with an assigned type
 02607                        anyNewConstraints = true;
 02608                        done = true;
 02609                        break;
 2610                      }
 02611                    }
 02612                  }
 02613                  if (done) {
 02614                    break;
 2615                  }
 02616                }
 02617              }
 02618              if (anyNewConstraints) {
 02619                break;
 2620              }
 2621
 02622              foreach (var t in ss) {
 02623                var lowers = new HashSet<Type>();
 02624                var uppers = new HashSet<Type>();
 02625                foreach (var c in AllTypeConstraints) {
 02626                  var super = c.Super.NormalizeExpand();
 02627                  var sub = c.Sub.NormalizeExpand();
 02628                  if (t.Equals(super)) {
 02629                    lowers.Add(sub);
 02630                  }
 2631
 02632                  if (t.Equals(sub)) {
 02633                    uppers.Add(super);
 02634                  }
 02635                }
 2636
 02637                if (uppers.Count == 0) {
 02638                  if (lowers.Count == 1) {
 02639                    var em = lowers.GetEnumerator();
 02640                    em.MoveNext();
 02641                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02642                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSubErrorMsg,
 02643                        "Decision: {0} is decided to be {1} because the latter is a lower bound to the proxy and there i
 02644                        t, em.Current);
 02645                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02646                      anyNewConstraints = true;
 02647                      break;
 2648                    }
 02649                  }
 02650                }
 02651                if (lowers.Count == 0) {
 02652                  if (uppers.Count == 1) {
 02653                    var em = uppers.GetEnumerator();
 02654                    em.MoveNext();
 02655                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02656                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSuperErrorMsg,
 02657                        "Decision: {0} is decided to be {1} because the latter is an upper bound to the proxy and there 
 02658                        t, em.Current);
 02659                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02660                      anyNewConstraints = true;
 02661                      break;
 2662                    }
 02663                  }
 02664                }
 02665              }
 2666
 02667              break;
 2668            }
 2669
 2670          case 12:
 2671            // we're so out of here
 02672            return;
 2673        }
 25830102674        if (anyNewConstraints) {
 7631602675          state = 0;
 18198502676        } else {
 10566902677          state++;
 10566902678        }
 18198502679      }
 1157252680    }
 2681
 178002682    TypeProxy NewIntegerBasedProxy(IToken tok) {
 2683      Contract.Requires(tok != null);
 178002684      var proxy = new InferredTypeProxy();
 178002685      ConstrainSubtypeRelation(new IntVarietiesSupertype(), proxy, tok, "integer literal used as if it had type {0}", pr
 178002686      return proxy;
 178002687    }
 2688
 02689    private bool ContainsAsTypeParameter(Type t, Type u) {
 02690      if (t.Equals(u)) {
 02691        return true;
 2692      }
 2693
 02694      if (t is UserDefinedType udt) {
 02695        foreach (var tp in udt.TypeArgs) {
 02696          if (ContainsAsTypeParameter(tp, u)) {
 02697            return true;
 2698          }
 02699        }
 02700      }
 02701      if (t is CollectionType st) {
 02702        foreach (var tp in st.TypeArgs) {
 02703          if (ContainsAsTypeParameter(tp, u)) {
 02704            return true;
 2705          }
 02706        }
 02707      }
 02708      return false;
 02709    }
 2710
 531194302711    private void AddAllProxies(Type type, HashSet<TypeProxy> proxies) {
 2712      Contract.Requires(type != null);
 2713      Contract.Requires(proxies != null);
 531194302714      var proxy = type as TypeProxy;
 800802602715      if (proxy != null) {
 269608302716        proxies.Add(proxy);
 531194302717      } else {
 1072158002718        foreach (var ta in type.TypeArgs) {
 95800002719          AddAllProxies(ta, proxies);
 95800002720        }
 261586002721      }
 531194302722    }
 2723
 2724    /// <summary>
 2725    /// Set "lhs" to the join of "rhss" and "lhs.Subtypes, if possible.
 2726    /// Returns "true' if something was done, or "false" otherwise.
 2727    /// </summary>
 1421400002728    private bool ProcessAssignable(TypeProxy lhs, List<Type> rhss) {
 2729      Contract.Requires(lhs != null && lhs.T == null);
 2730      Contract.Requires(rhss != null);
 1421400002731      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02732        Console.Write("DEBUG: ProcessAssignable: {0} with rhss:", lhs);
 02733        foreach (var rhs in rhss) {
 02734          Options.OutputWriter.Write(" {0}", rhs);
 02735        }
 02736        Options.OutputWriter.Write(" subtypes:");
 02737        foreach (var sub in lhs.SubtypesKeepConstraints) {
 02738          Options.OutputWriter.Write(" {0}", sub);
 02739        }
 02740        Options.OutputWriter.WriteLine();
 02741      }
 1421400002742      Type join = null;
 6080852702743      foreach (var rhs in rhss) {
 2556902402744        if (rhs is TypeProxy) { return false; }
 48021902745        join = join == null ? rhs : Type.Join(join, rhs, builtIns);
 48021902746      }
 2917556602747      foreach (var sub in lhs.SubtypesKeepConstraints) {
 1742656702748        if (sub is TypeProxy) { return false; }
 199702749        join = join == null ? sub : Type.Join(join, sub, builtIns);
 199702750      }
 5543402751      if (join == null) {
 1255902752        return false;
 3031602753      } else if (Reaches(join, lhs, 1, new HashSet<TypeProxy>())) {
 2754        // would cause a cycle, so don't do it
 02755        return false;
 3031602756      } else {
 3031602757        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02758          Options.OutputWriter.WriteLine("DEBUG: ProcessAssignable: assigning proxy {0}.T := {1}", lhs, join);
 02759        }
 3031602760        lhs.T = join;
 3031602761        return true;
 2762      }
 1421400002763    }
 2764
 2765    /// <summary>
 2766    /// Convert each Assignable(A, B) constraint into a subtyping constraint A :> B,
 2767    /// provided that:
 2768    ///  - B is a non-proxy, and
 2769    ///  - either "proxySpecialization" is null or some proxy in "proxySpecializations" prominently appears in A.
 2770    /// </summary>
 476902771    bool ConvertAssignableToSubtypeConstraints(ISet<TypeProxy>/*?*/ proxySpecializations) {
 476902772      var anyNewConstraints = false;
 2773      // If (the head of) the RHS of an Assignable is known, convert the XConstraint into a subtyping constraint
 476902774      var allX = AllXConstraints;
 476902775      AllXConstraints = new List<XConstraint>();
 629572802776      foreach (var xc in allX) {
 304521302777        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() is NonProxyType) {
 95140602778          var t0 = xc.Types[0].NormalizeExpand();
 95140602779          if (proxySpecializations == null
 95140602780            || proxySpecializations.Contains(t0)
 98046502781            || t0.TypeArgs.Exists(ta => proxySpecializations.Contains(ta))) {
 2905902782            ConstrainSubtypeRelation(t0, xc.Types[1], xc.errorMsg, true);
 2905902783            anyNewConstraints = true;
 2905902784            continue;
 2785          }
 92234702786        }
 206474802787        AllXConstraints.Add(xc);
 206474802788      }
 476902789      return anyNewConstraints;
 476902790    }
 2791
 237202792    bool TightenUpEquatable(ISet<TypeProxy> proxiesOfInterest) {
 2793      Contract.Requires(proxiesOfInterest != null);
 237202794      var anyNewConstraints = false;
 237202795      var allX = AllXConstraints;
 237202796      AllXConstraints = new List<XConstraint>();
 603156602797      foreach (var xc in allX) {
 201059902798        if (xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") {
 244902799          var t0 = xc.Types[0].NormalizeExpandKeepConstraints();
 244902800          var t1 = xc.Types[1].NormalizeExpandKeepConstraints();
 245102801          if (proxiesOfInterest.Contains(t0) || proxiesOfInterest.Contains(t1)) {
 202802            ConstrainSubtypeRelation_Equal(t0, t1, xc.errorMsg);
 202803            anyNewConstraints = true;
 202804            continue;
 2805          }
 244702806        }
 200814802807        AllXConstraints.Add(xc);
 200814802808      }
 237202809      return anyNewConstraints;
 237202810    }
 2811
 5565193402812    void ProcessOneSubtypingConstraintAndItsSubs(TypeConstraint c, ISet<TypeConstraint> processed, bool fullStrength, re
 2813      Contract.Requires(c != null);
 2814      Contract.Requires(processed != null);
 7139552402815      if (processed.Contains(c)) {
 1574359002816        return;  // our job has already been done, or is at least in progress
 2817      }
 3990834402818      processed.Add(c);
 2819
 3990834402820      var super = c.Super.NormalizeExpandKeepConstraints();
 3990834402821      var sub = c.Sub.NormalizeExpandKeepConstraints();
 2822      // Process all subtype types before going on
 3990834402823      var subProxy = sub as TypeProxy;
 7932977502824      if (subProxy != null) {
 16550420102825        foreach (var cc in subProxy.SubtypeConstraints) {
 1574663602826          ProcessOneSubtypingConstraintAndItsSubs(cc, processed, fullStrength, ref anyNewConstraints);
 1574663602827        }
 3942143102828      }
 2829      // the processing may have assigned some proxies, so we'll refresh super and sub
 3990834402830      super = super.NormalizeExpandKeepConstraints();
 3990834402831      sub = sub.NormalizeExpandKeepConstraints();
 2832
 4015471902833      if (super.Equals(sub)) {
 2834        // the constraint is satisfied, so just drop it
 3995400602835      } else if ((super is NonProxyType || super is ArtificialType) && sub is NonProxyType) {
 4566202836        ImposeSubtypingConstraint(super, sub, c.ErrMsg);
 4566202837        anyNewConstraints = true;
 3966300302838      } else if (AssignKnownEnd(sub as TypeProxy, true, fullStrength)) {
 103402839        anyNewConstraints = true;
 3961630702840      } else if (sub is TypeProxy && fullStrength && AssignKnownEndsFullstrength((TypeProxy)sub)) {
 02841        anyNewConstraints = true;
 3961527302842      } else {
 2843        // keep the constraint for now
 3961527302844        AllTypeConstraints.Add(c);
 3961527302845      }
 5565193402846    }
 2847
 15463002848    void ProcessFullStrength_SubDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2849      Contract.Requires(t != null);
 2850      Contract.Requires(processed != null);
 15463002851      var proxy = t.NormalizeExpand() as TypeProxy;
 27851102852      if (proxy != null) {
 21133102853        if (processed.Contains(proxy)) {
 8745002854          return;  // our job has already been done, or is at least in progress
 2855        }
 3643102856        processed.Add(proxy);
 2857
 29529302858        foreach (var u in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 6200002859          ProcessFullStrength_SubDirection(u, processed, ref anyNewConstraints);
 6200002860        }
 3643102861        proxy = proxy.NormalizeExpand() as TypeProxy;
 3647302862        if (proxy != null && AssignKnownEndsFullstrength_SubDirection(proxy)) {
 4202863          anyNewConstraints = true;
 4202864        }
 3643102865      }
 15463002866    }
 2867
 13011402868    void ProcessFullStrength_SuperDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2869      Contract.Requires(t != null);
 2870      Contract.Requires(processed != null);
 13011402871      var proxy = t.NormalizeExpand() as TypeProxy;
 22080002872      if (proxy != null) {
 14699802873        if (processed.Contains(proxy)) {
 5631202874          return;  // our job has already been done, or is at least in progress
 2875        }
 3437402876        processed.Add(proxy);
 2877
 26694902878        foreach (var u in proxy.Supertypes) {
 5460902879          ProcessFullStrength_SuperDirection(u, processed, ref anyNewConstraints);
 5460902880        }
 3437402881        proxy = proxy.NormalizeExpand() as TypeProxy;
 4357902882        if (proxy != null && AssignKnownEndsFullstrength_SuperDirection(proxy)) {
 920502883          anyNewConstraints = true;
 920502884        }
 3437402885      }
 13011402886    }
 2887
 2888    /// <summary>
 2889    /// Returns true if anything happened.
 2890    /// </summary>
 7939731902891    bool AssignKnownEnd(TypeProxy proxy, bool keepConstraints, bool fullStrength) {
 2892      Contract.Requires(proxy == null || proxy.T == null);  // caller is supposed to have called NormalizeExpand
 9625446902893      if (proxy == null) {
 2894        // nothing to do
 1685715002895        return false;
 2896      }
 2897      // ----- first, go light; also, prefer subtypes over supertypes
 6254016902898      IEnumerable<Type> subTypes = keepConstraints ? proxy.SubtypesKeepConstraints : proxy.Subtypes;
 5126355042899      foreach (var su in subTypes) {
 9773067102900        DetermineRootLeaf(su, out var isRoot, out _, out var headRoot, out _);
 9773067102901        Contract.Assert(!isRoot || headRoot);  // isRoot ==> headRoot
 9777012102902        if (isRoot) {
 3945002903          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2904            // adding a constraint here would cause a bad cycle, so we don't
 3945002905          } else {
 3945002906            AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 3945002907            return true;
 2908          }
 9770401102909        } else if (headRoot) {
 1279002910          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2911            // adding a constraint here would cause a bad cycle, so we don't
 1279002912          } else {
 1279002913            AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 1279002914            return true;
 2915          }
 02916        }
 9767843102917      }
 6248792902918      if (fullStrength) {
 02919        IEnumerable<Type> superTypes = keepConstraints ? proxy.SupertypesKeepConstraints : proxy.Supertypes;
 02920        foreach (var su in superTypes) {
 02921          DetermineRootLeaf(su, out _, out var isLeaf, out _, out var headLeaf);
 02922          Contract.Assert(!isLeaf || headLeaf);  // isLeaf ==> headLeaf
 02923          if (isLeaf) {
 02924            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2925              // adding a constraint here would cause a bad cycle, so we don't
 02926            } else {
 02927              AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 02928              return true;
 2929            }
 02930          } else if (headLeaf) {
 02931            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2932              // adding a constraint here would cause a bad cycle, so we don't
 02933            } else {
 02934              AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 02935              return true;
 2936            }
 02937          }
 02938        }
 02939      }
 6248792902940      return false;
 7939731902941    }
 2942
 02943    bool AssignKnownEndsFullstrength(TypeProxy proxy) {
 2944      Contract.Requires(proxy != null);
 2945      // ----- continue with full strength
 2946      // If the join of the subtypes exists, use it
 02947      var joins = new List<Type>();
 02948      foreach (var su in proxy.Subtypes) {
 02949        if (su is TypeProxy) {
 02950          continue;  // don't include proxies in the meet computation
 2951        }
 02952        int i = 0;
 02953        for (; i < joins.Count; i++) {
 02954          var j = Type.Join(joins[i], su, builtIns);
 02955          if (j != null) {
 02956            joins[i] = j;
 02957            break;
 2958          }
 02959        }
 02960        if (i == joins.Count) {
 2961          // we went to the end without finding a place to meet up
 02962          joins.Add(su);
 02963        }
 02964      }
 02965      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 2966        // we were able to compute a meet of all the subtyping constraints, so use it
 02967        AssignProxyAndHandleItsConstraints(proxy, joins[0]);
 02968        return true;
 2969      }
 2970      // If the meet of the supertypes exists, use it
 02971      var meets = new List<Type>();
 02972      foreach (var su in proxy.Supertypes) {
 02973        if (su is TypeProxy) {
 02974          continue;  // don't include proxies in the meet computation
 2975        }
 02976        int i = 0;
 02977        for (; i < meets.Count; i++) {
 02978          var j = Type.Meet(meets[i], su, builtIns);
 02979          if (j != null) {
 02980            meets[i] = j;
 02981            break;
 2982          }
 02983        }
 02984        if (i == meets.Count) {
 2985          // we went to the end without finding a place to meet
 02986          meets.Add(su);
 02987        }
 02988      }
 02989      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 2990        // we were able to compute a meet of all the subtyping constraints, so use it
 02991        AssignProxyAndHandleItsConstraints(proxy, meets[0]);
 02992        return true;
 2993      }
 2994
 02995      return false;
 02996    }
 2997
 3643002998    bool AssignKnownEndsFullstrength_SubDirection(TypeProxy proxy) {
 2999      Contract.Requires(proxy != null && proxy.T == null);
 3000      // If the join the subtypes exists, use it
 3643003001      var joins = new List<Type>();
 3643003002      var proxySubs = new HashSet<TypeProxy>();
 3643003003      proxySubs.Add(proxy);
 29528403004      foreach (var su in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 12394603005        if (su is TypeProxy) {
 6194803006          proxySubs.Add((TypeProxy)su);
 6199803007        } else {
 5003008          int i = 0;
 5803009          for (; i < joins.Count; i++) {
 803010            var j = Type.Join(joins[i], su, builtIns);
 1603011            if (j != null) {
 803012              joins[i] = j;
 803013              break;
 3014            }
 03015          }
 9203016          if (i == joins.Count) {
 3017            // we went to the end without finding a place to join in
 4203018            joins.Add(su);
 4203019          }
 5003020        }
 6199803021      }
 3647203022      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 3023        // We were able to compute a join of all the subtyping constraints, so use it.
 3024        // Well, maybe.  If "join[0]" denotes a non-null type and "proxy" is something
 3025        // that could be assigned "null", then set "proxy" to the nullable version of "join[0]".
 3026        // Stated differently, think of an applicable "IsNullableRefType" constraint as
 3027        // being part of the join computation, essentially throwing in a "...?".
 3028        // Except: If the join is a tight bound--meaning, it is also a meet--then pick it
 3029        // after all, because that seems to give rise to less confusing error messages.
 4203030        if (joins[0].IsNonNullRefType) {
 03031          Type meet = null;
 03032          if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null && Type.SameHead(joi
 3033            // leave it
 03034          } else {
 03035            CloseOverAssignableRhss(proxySubs);
 03036            if (HasApplicableNullableRefTypeConstraint(proxySubs)) {
 03037              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 03038                Options.OutputWriter.WriteLine("DEBUG: Found join {0} for proxy {1}, but weakening it to {2}", joins[0],
 03039              }
 03040              AssignProxyAndHandleItsConstraints(proxy, joins[0].NormalizeExpand(), true);
 03041              return true;
 3042            }
 03043          }
 03044        }
 4203045        AssignProxyAndHandleItsConstraints(proxy, joins[0], true);
 4203046        return true;
 3047      }
 3638803048      return false;
 3643003049    }
 3050
 03051    private void CloseOverAssignableRhss(ISet<TypeProxy> proxySet) {
 3052      Contract.Requires(proxySet != null);
 03053      while (true) {
 03054        var moreChanges = false;
 03055        foreach (var xc in AllXConstraints) {
 03056          if (xc.ConstraintName == "Assignable") {
 03057            var source = xc.Types[0].Normalize() as TypeProxy;
 03058            var sink = xc.Types[1].Normalize() as TypeProxy;
 03059            if (source != null && sink != null && proxySet.Contains(source) && !proxySet.Contains(sink)) {
 03060              proxySet.Add(sink);
 03061              moreChanges = true;
 03062            }
 03063          }
 03064        }
 03065        if (!moreChanges) {
 03066          return;
 3067        }
 03068      }
 03069    }
 03070    private bool HasApplicableNullableRefTypeConstraint(ISet<TypeProxy> proxySet) {
 3071      Contract.Requires(proxySet != null);
 03072      var nullableProxies = new HashSet<TypeProxy>();
 03073      foreach (var xc in AllXConstraints) {
 03074        if (xc.ConstraintName == "IsNullableRefType") {
 03075          var npr = xc.Types[0].Normalize() as TypeProxy;
 03076          if (npr != null) {
 03077            nullableProxies.Add(npr);
 03078          }
 03079        }
 03080      }
 03081      return proxySet.Any(nullableProxies.Contains);
 03082    }
 8903083    private bool HasApplicableNullableRefTypeConstraint_SubDirection(TypeProxy proxy) {
 3084      Contract.Requires(proxy != null);
 8903085      var nullableProxies = new HashSet<TypeProxy>();
 53403086      foreach (var xc in AllXConstraints) {
 17803087        if (xc.ConstraintName == "IsNullableRefType") {
 8903088          var npr = xc.Types[0].Normalize() as TypeProxy;
 17803089          if (npr != null) {
 8903090            nullableProxies.Add(npr);
 8903091          }
 8903092        }
 8903093      }
 8903094      return HasApplicableNullableRefTypeConstraint_SubDirection_aux(proxy, nullableProxies, new HashSet<TypeProxy>());
 8903095    }
 8903096    private bool HasApplicableNullableRefTypeConstraint_SubDirection_aux(TypeProxy proxy, ISet<TypeProxy> nullableProxie
 3097      Contract.Requires(proxy != null);
 3098      Contract.Requires(nullableProxies != null);
 3099      Contract.Requires(visitedProxies != null);
 3100
 8903101      if (visitedProxies.Contains(proxy)) {
 03102        return false;
 3103      }
 8903104      visitedProxies.Add(proxy);
 3105
 17803106      if (nullableProxies.Contains(proxy)) {
 8903107        return true;
 3108      }
 3109
 03110      foreach (var sub in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 03111        var psub = sub as TypeProxy;
 03112        if (psub != null && HasApplicableNullableRefTypeConstraint_SubDirection_aux(psub, nullableProxies, visitedProxie
 03113          return true;
 3114        }
 03115      }
 03116      return false;
 8903117    }
 3118
 3316303119    bool AssignKnownEndsFullstrength_SuperDirection(TypeProxy proxy) {
 3120      Contract.Requires(proxy != null && proxy.T == null);
 3121      // First, compute the the join of the Assignable LHSs.  Then, compute
 3122      // the meet of that join and the supertypes.
 3316303123      var joins = new List<Type>();
 966098703124      foreach (var xc in AllXConstraints) {
 320337503125        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() == proxy) {
 1620903126          var su = xc.Types[0].Normalize();
 2744803127          if (su is TypeProxy) {
 1123903128            continue; // don't include proxies in the join computation
 3129          }
 497003130          int i = 0;
 508803131          for (; i < joins.Count; i++) {
 11803132            var j = Type.Join(joins[i], su, builtIns);
 23603133            if (j != null) {
 11803134              joins[i] = j;
 11803135              break;
 3136            }
 03137          }
 982203138          if (i == joins.Count) {
 3139            // we went to the end without finding a place to join in
 485203140            joins.Add(su);
 485203141          }
 497003142        }
 317592703143      }
 3144      // If the meet of the supertypes exists, use it
 3316303145      var meets = new List<Type>(joins);
 25158903146      foreach (var su in proxy.SupertypesKeepConstraints) {
 8149803147        if (su is TypeProxy) {
 3079803148          continue;  // don't include proxies in the meet computation
 3149        }
 1990203150        int i = 0;
 2532703151        for (; i < meets.Count; i++) {
 542503152          var j = Type.Meet(meets[i], su, builtIns);
 1085003153          if (j != null) {
 542503154            meets[i] = j;
 542503155            break;
 3156          }
 03157        }
 3437903158        if (i == meets.Count) {
 3159          // we went to the end without finding a place to meet up
 1447703160          meets.Add(su);
 1447703161        }
 1990203162      }
 4236803163      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 3164        // we were able to compute a meet of all the subtyping constraints, so use it
 920503165        AssignProxyAndHandleItsConstraints(proxy, meets[0], true);
 920503166        return true;
 3167      }
 2395803168      return false;
 3316303169    }
 3170
 3171    int _reaches_recursion;
 29655203172    private bool Reaches(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 29655203173      if (_reaches_recursion == 20) {
 03174        Contract.Assume(false);  // possible infinite recursion
 03175      }
 29655203176      _reaches_recursion++;
 29655203177      var b = Reaches_aux(t, proxy, direction, visited);
 29655203178      _reaches_recursion--;
 29655203179      return b;
 29655203180    }
 29655203181    private bool Reaches_aux(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 3182      Contract.Requires(t != null);
 3183      Contract.Requires(proxy != null);
 3184      Contract.Requires(visited != null);
 29655203185      t = t.NormalizeExpand();
 29655203186      var tproxy = t as TypeProxy;
 48670703187      if (tproxy == null) {
 19015503188        var polarities = Type.GetPolarities(t).ConvertAll(TypeParameter.Direction);
 19015503189        Contract.Assert(polarities != null);
 19015503190        Contract.Assert(polarities.Count <= t.TypeArgs.Count);
 79580403191        for (int i = 0; i < polarities.Count; i++) {
 13849803192          if (Reaches(t.TypeArgs[i], proxy, direction * polarities[i], visited)) {
 03193            return true;
 3194          }
 13849803195        }
 19015503196        return false;
 10640303197      } else if (tproxy == proxy) {
 603198        return true;
 13479403199      } else if (visited.Contains(tproxy)) {
 2840303200        return false;
 7798803201      } else {
 7798803202        visited.Add(tproxy);
 14420303203        if (0 <= direction && tproxy.Subtypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03204          return true;
 3205        }
 7798803206        if (direction <= 0 && tproxy.Supertypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03207          return true;
 3208        }
 7798803209        return false;
 3210      }
 29655203211    }
 3212
 3213    /// <summary>
 3214    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3215    /// </summary>
 17803216    void ResolveClassMemberBodiesInitial(TopLevelDeclWithMembers cl) {
 3217      Contract.Requires(cl != null);
 3218      Contract.Requires(currentClass == null);
 3219      Contract.Requires(AllTypeConstraints.Count == 0);
 3220      Contract.Ensures(currentClass == null);
 3221      Contract.Ensures(AllTypeConstraints.Count == 0);
 3222
 17803223      currentClass = cl;
 632253224      foreach (MemberDecl member in cl.Members) {
 192953225        Contract.Assert(VisibleInScope(member));
 192953226        if (member is ConstantField { Rhs: { } } constantField) {
 03227          var resolutionContext = new ResolutionContext(constantField, false);
 03228          scope.PushMarker();
 03229          if (constantField.IsStatic || currentClass == null || !currentClass.AcceptThis) {
 03230            scope.AllowInstance = false;
 03231          }
 03232          ResolveExpression(constantField.Rhs, resolutionContext);
 03233          scope.PopMarker();
 03234          AddAssignableConstraint(constantField.tok, constantField.Type, constantField.Rhs.Type,
 03235            "type for constant '" + constantField.Name + "' is '{0}', but its initialization value type is '{1}'");
 03236          SolveAllTypeConstraints();
 03237        }
 192953238      }
 17803239      currentClass = null;
 17803240    }
 3241
 3242    /// <summary>
 3243    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3244    /// </summary>
 17803245    void ResolveClassMemberBodies(TopLevelDeclWithMembers cl) {
 3246      Contract.Requires(cl != null);
 3247      Contract.Requires(currentClass == null);
 3248      Contract.Requires(AllTypeConstraints.Count == 0);
 3249      Contract.Ensures(currentClass == null);
 3250      Contract.Ensures(AllTypeConstraints.Count == 0);
 3251
 17803252      currentClass = cl;
 632253253      foreach (MemberDecl member in cl.Members) {
 192953254        Contract.Assert(VisibleInScope(member));
 197403255        if (member is Field) {
 4453256          var resolutionContext = new ResolutionContext(new NoContext(currentClass.EnclosingModuleDefinition), false);
 4453257          scope.PushMarker();
 4453258          if (member.IsStatic) {
 03259            scope.AllowInstance = false;
 03260          }
 4453261          ResolveAttributes(member, resolutionContext, true);
 4453262          scope.PopMarker();
 3263
 330053264        } else if (member is Function function) {
 137103265          var ec = reporter.Count(ErrorLevel.Error);
 137103266          allTypeParameters.PushMarker();
 137103267          ResolveTypeParameters(function.TypeArgs, false, function);
 3268
 137103269          function.Resolve(this);
 137103270          allTypeParameters.PopMarker();
 137103271          if (function is ExtremePredicate { PrefixPredicate: { } prefixPredicate } && ec == reporter.Count(ErrorLevel.E
 03272            allTypeParameters.PushMarker();
 03273            ResolveTypeParameters(prefixPredicate.TypeArgs, false, prefixPredicate);
 03274            prefixPredicate.Resolve(this);
 03275            allTypeParameters.PopMarker();
 03276          }
 3277
 239903278        } else if (member is Method method) {
 51403279          var ec = reporter.Count(ErrorLevel.Error);
 51403280          allTypeParameters.PushMarker();
 51403281          ResolveTypeParameters(method.TypeArgs, false, method);
 51403282          method.Resolve(this);
 51403283          allTypeParameters.PopMarker();
 51403284          if (method is ExtremeLemma { PrefixLemma: { } prefixLemma } && ec == reporter.Count(ErrorLevel.Error)) {
 03285            allTypeParameters.PushMarker();
 03286            ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03287            prefixLemma.Resolve(this);
 03288            allTypeParameters.PopMarker();
 03289          }
 3290
 51403291        } else {
 03292          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 3293        }
 192953294        Contract.Assert(AllTypeConstraints.Count == 0);
 192953295      }
 17803296      currentClass = null;
 17803297    }
 3298
 3299    /// <summary>
 3300    /// Assumes type parameters have already been pushed
 3301    /// </summary>
 03302    void ResolveCtorTypes(DatatypeDecl/*!*/ dt, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies, Graph<CoDatatypeDecl/*!*/
 3303      Contract.Requires(dt != null);
 3304      Contract.Requires(dependencies != null);
 3305      Contract.Requires(coDependencies != null);
 03306      foreach (DatatypeCtor ctor in dt.Ctors) {
 3307
 03308        ctor.EnclosingDatatype = dt;
 3309
 03310        allTypeParameters.PushMarker();
 03311        ResolveCtorSignature(ctor, dt.TypeArgs);
 03312        allTypeParameters.PopMarker();
 3313
 03314        if (dt is IndDatatypeDecl) {
 3315          // The dependencies of interest among inductive datatypes are all (inductive data)types mentioned in the param
 03316          var idt = (IndDatatypeDecl)dt;
 03317          dependencies.AddVertex(idt);
 03318          foreach (Formal p in ctor.Formals) {
 03319            AddDatatypeDependencyEdge(idt, p.Type, dependencies);
 03320          }
 03321        } else {
 3322          // The dependencies of interest among codatatypes are just the top-level types of parameters.
 03323          var codt = (CoDatatypeDecl)dt;
 03324          coDependencies.AddVertex(codt);
 03325          foreach (var p in ctor.Formals) {
 03326            var co = p.Type.AsCoDatatype;
 03327            if (co != null && codt.EnclosingModuleDefinition == co.EnclosingModuleDefinition) {
 03328              coDependencies.AddEdge(codt, co);
 03329            }
 03330          }
 03331        }
 03332      }
 03333    }
 3334
 03335    void ResolveCtorSignature(DatatypeCtor ctor, List<TypeParameter> dtTypeArguments) {
 3336      Contract.Requires(ctor != null);
 3337      Contract.Requires(ctor.EnclosingDatatype != null);
 3338      Contract.Requires(dtTypeArguments != null);
 03339      foreach (Formal p in ctor.Formals) {
 03340        ResolveType(p.tok, p.Type, ctor.EnclosingDatatype, ResolveTypeOptionEnum.AllowPrefix, dtTypeArguments);
 03341      }
 03342    }
 3343
 03344    void AddDatatypeDependencyEdge(IndDatatypeDecl dt, Type tp, Graph<IndDatatypeDecl> dependencies) {
 3345      Contract.Requires(dt != null);
 3346      Contract.Requires(tp != null);
 3347      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 3348
 03349      tp = tp.NormalizeExpand();
 03350      var dependee = tp.AsIndDatatype;
 03351      if (dependee != null && dt.EnclosingModuleDefinition == dependee.EnclosingModuleDefinition) {
 03352        dependencies.AddEdge(dt, dependee);
 03353        foreach (var ta in ((UserDefinedType)tp).TypeArgs) {
 03354          AddDatatypeDependencyEdge(dt, ta, dependencies);
 03355        }
 03356      }
 03357    }
 3358
 03359    public void ResolveFrameExpressionTopLevel(FrameExpression fe, FrameExpressionUse use, ICodeContext codeContext) {
 03360      ResolveFrameExpression(fe, use, new ResolutionContext(codeContext, false));
 03361    }
 3362
 03363    void ResolveFrameExpression(FrameExpression fe, FrameExpressionUse use, ResolutionContext resolutionContext) {
 3364      Contract.Requires(fe != null);
 3365      Contract.Requires(resolutionContext != null);
 3366
 03367      ResolveExpression(fe.E, resolutionContext);
 03368      Type t = fe.E.Type;
 03369      Contract.Assert(t != null);  // follows from postcondition of ResolveExpression
 03370      var eventualRefType = new InferredTypeProxy();
 03371      if (use == FrameExpressionUse.Reads) {
 03372        AddXConstraint(fe.E.tok, "ReadsFrame", t, eventualRefType,
 03373          "a reads-clause expression must denote an object, a set/iset/multiset/seq of objects, or a function to a set/i
 03374      } else {
 03375        AddXConstraint(fe.E.tok, "ModifiesFrame", t, eventualRefType,
 03376          use == FrameExpressionUse.Modifies ?
 03377          "a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})" :
 03378          "an unchanged expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})");
 03379      }
 03380      if (fe.FieldName != null) {
 03381        var member = ResolveMember(fe.E.tok, eventualRefType, fe.FieldName, out var tentativeReceiverType);
 03382        var ctype = (UserDefinedType)tentativeReceiverType;  // correctness of cast follows from the DenotesClass test a
 03383        if (member == null) {
 3384          // error has already been reported by ResolveMember
 03385        } else if (!(member is Field)) {
 03386          reporter.Error(MessageSource.Resolver, fe.E, "member {0} in type {1} does not refer to a field", fe.FieldName,
 03387        } else if (member is ConstantField) {
 03388          reporter.Error(MessageSource.Resolver, fe.E, "expression is not allowed to refer to constant field {0}", fe.Fi
 03389        } else {
 03390          Contract.Assert(ctype != null && ctype.ResolvedClass != null);  // follows from postcondition of ResolveMember
 03391          fe.Field = (Field)member;
 03392        }
 03393      }
 03394    }
 3395
 03396    void ResolveIterator(IteratorDecl iter) {
 3397      Contract.Requires(iter != null);
 3398      Contract.Requires(currentClass == null);
 3399      Contract.Ensures(currentClass == null);
 3400
 03401      var initialErrorCount = reporter.Count(ErrorLevel.Error);
 3402
 3403      // Add in-parameters to the scope, but don't care about any duplication errors, since they have already been repor
 03404      scope.PushMarker();
 03405      scope.AllowInstance = false;  // disallow 'this' from use, which means that the special fields and methods added a
 03406      iter.Ins.ForEach(p => scope.Push(p.Name, p));
 03407      ResolveParameterDefaultValues(iter.Ins, new ResolutionContext(iter, false));
 3408
 3409      // Start resolving specification...
 3410      // we start with the decreases clause, because the _decreases<n> fields were only given type proxies before; we'll
 3411      // the types only after resolving the decreases clause (and it may be that some of resolution has already seen use
 3412      // these fields; so, with no further ado, here we go
 03413      ResolveAttributes(iter.Decreases, new ResolutionContext(iter, false));
 03414      Contract.Assert(iter.Decreases.Expressions.Count == iter.DecreasesFields.Count);
 03415      for (var i = 0; i < iter.Decreases.Expressions.Count; i++) {
 03416        var e = iter.Decreases.Expressions[i];
 03417        ResolveExpression(e, new ResolutionContext(iter, false));
 3418        // any type is fine, but associate this type with the corresponding _decreases<n> field
 03419        var d = iter.DecreasesFields[i];
 3420        // If the following type constraint does not hold, then: Bummer, there was a use--and a bad use--of the field be
 03421        ConstrainSubtypeRelation(d.Type, e.Type, e, "type of field {0} is {1}, but has been constrained elsewhere to be 
 03422      }
 03423      foreach (FrameExpression fe in iter.Reads.Expressions) {
 03424        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Reads, iter);
 03425      }
 03426      ResolveAttributes(iter.Modifies, new ResolutionContext(iter, false));
 03427      foreach (FrameExpression fe in iter.Modifies.Expressions) {
 03428        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Modifies, iter);
 03429      }
 03430      foreach (AttributedExpression e in iter.Requires) {
 03431        ResolveAttributes(e, new ResolutionContext(iter, false));
 03432        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03433        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03434        ConstrainTypeExprBool(e.E, "Precondition must be a boolean (got {0})");
 03435      }
 3436
 03437      scope.PopMarker();  // for the in-parameters
 3438
 3439      // We resolve the rest of the specification in an instance context.  So mentions of the in- or yield-parameters
 3440      // get resolved as field dereferences (with an implicit "this")
 03441      scope.PushMarker();
 03442      currentClass = iter;
 03443      Contract.Assert(scope.AllowInstance);
 3444
 03445      foreach (AttributedExpression e in iter.YieldRequires) {
 03446        ResolveAttributes(e, new ResolutionContext(iter, false));
 03447        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03448        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03449        ConstrainTypeExprBool(e.E, "Yield precondition must be a boolean (got {0})");
 03450      }
 03451      foreach (AttributedExpression e in iter.YieldEnsures) {
 03452        ResolveAttributes(e, new ResolutionContext(iter, true));
 03453        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03454        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03455        ConstrainTypeExprBool(e.E, "Yield postcondition must be a boolean (got {0})");
 03456      }
 03457      foreach (AttributedExpression e in iter.Ensures) {
 03458        ResolveAttributes(e, new ResolutionContext(iter, true));
 03459        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03460        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03461        ConstrainTypeExprBool(e.E, "Postcondition must be a boolean (got {0})");
 03462      }
 03463      SolveAllTypeConstraints();
 3464
 03465      var postSpecErrorCount = reporter.Count(ErrorLevel.Error);
 3466
 3467      // Resolve body
 03468      if (iter.Body != null) {
 03469        DominatingStatementLabels.PushMarker();
 03470        foreach (var req in iter.Requires) {
 03471          if (req.Label != null) {
 03472            if (DominatingStatementLabels.Find(req.Label.Name) != null) {
 03473              reporter.Error(MessageSource.Resolver, req.Label.Tok, "assert label shadows a dominating label");
 03474            } else {
 03475              var rr = DominatingStatementLabels.Push(req.Label.Name, req.Label);
 03476              Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expec
 03477            }
 03478          }
 03479        }
 03480        ResolveBlockStatement(iter.Body, ResolutionContext.FromCodeContext(iter));
 03481        DominatingStatementLabels.PopMarker();
 03482        SolveAllTypeConstraints();
 03483      }
 3484
 03485      currentClass = null;
 03486      scope.PopMarker();  // pop off the AllowInstance setting
 3487
 03488      if (postSpecErrorCount == initialErrorCount) {
 03489        iter.CreateIteratorMethodSpecs(this);
 03490      }
 03491    }
 3492
 3493    /// <summary>
 3494    /// Checks if lhs, which is expected to be a successfully resolved expression, denotes something
 3495    /// that can be assigned to.  In particular, this means that lhs denotes a mutable variable, field,
 3496    /// or array element.  If a violation is detected, an error is reported.
 3497    /// </summary>
 3924003498    public void CheckIsLvalue(Expression lhs, ResolutionContext resolutionContext) {
 3499      Contract.Requires(lhs != null);
 3500      Contract.Requires(resolutionContext != null);
 7848003501      if (lhs is IdentifierExpr) {
 3924003502        var ll = (IdentifierExpr)lhs;
 3924003503        if (!ll.Var.IsMutable) {
 03504          reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable");
 03505        }
 3924003506      } else if (lhs is MemberSelectExpr) {
 03507        var ll = (MemberSelectExpr)lhs;
 03508        var field = ll.Member as Field;
 03509        if (field == null || !field.IsUserMutable) {
 03510          if (resolutionContext.InFirstPhaseConstructor && field is ConstantField cf && !cf.IsStatic && cf.Rhs == null) 
 03511            if (Expression.AsThis(ll.Obj) != null) {
 3512              // it's cool; this field can be assigned to here
 03513            } else {
 03514              reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field of 'this'");
 03515            }
 03516          } else {
 03517            reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field");
 03518          }
 03519        }
 03520      } else if (lhs is SeqSelectExpr) {
 03521        var ll = (SeqSelectExpr)lhs;
 03522        ConstrainSubtypeRelation(ResolvedArrayType(ll.Seq.tok, 1, new InferredTypeProxy(), resolutionContext, true), ll.
 03523          "LHS of array assignment must denote an array element (found {0})", ll.Seq.Type);
 03524        if (!ll.SelectOne) {
 03525          reporter.Error(MessageSource.Resolver, ll.Seq, "cannot assign to a range of array elements (try the 'forall' s
 03526        }
 03527      } else if (lhs is MultiSelectExpr) {
 3528        // nothing to check; this can only denote an array element
 03529      } else {
 03530        reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable or field");
 03531      }
 3924003532    }
 3533
 382003534    public void ResolveBlockStatement(BlockStmt blockStmt, ResolutionContext resolutionContext) {
 3535      Contract.Requires(blockStmt != null);
 3536      Contract.Requires(resolutionContext != null);
 3537
 382003538      if (blockStmt is DividedBlockStmt) {
 03539        var div = (DividedBlockStmt)blockStmt;
 03540        Contract.Assert(currentMethod is Constructor);  // divided bodies occur only in class constructors
 03541        Contract.Assert(!resolutionContext.InFirstPhaseConstructor);  // divided bodies are never nested
 03542        foreach (Statement ss in div.BodyInit) {
 03543          ResolveStatementWithLabels(ss, resolutionContext with { InFirstPhaseConstructor = true });
 03544        }
 03545        foreach (Statement ss in div.BodyProper) {
 03546          ResolveStatementWithLabels(ss, resolutionContext);
 03547        }
 382003548      } else {
 14728203549        foreach (Statement ss in blockStmt.Body) {
 4527403550          ResolveStatementWithLabels(ss, resolutionContext);
 4527403551        }
 382003552      }
 382003553    }
 3554
 4527403555    public void ResolveStatementWithLabels(Statement stmt, ResolutionContext resolutionContext) {
 3556      Contract.Requires(stmt != null);
 3557      Contract.Requires(resolutionContext != null);
 3558
 4527403559      enclosingStatementLabels.PushMarker();
 3560      // push labels
 9054803561      for (var l = stmt.Labels; l != null; l = l.Next) {
 03562        var lnode = l.Data;
 03563        Contract.Assert(lnode.Name != null);  // LabelNode's with .Label==null are added only during resolution of the b
 03564        var prev = enclosingStatementLabels.Find(lnode.Name);
 03565        if (prev == stmt) {
 03566          reporter.Error(MessageSource.Resolver, lnode.Tok, "duplicate label");
 03567        } else if (prev != null) {
 03568          reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows an enclosing label");
 03569        } else {
 03570          var r = enclosingStatementLabels.Push(lnode.Name, stmt);
 03571          Contract.Assert(r == Scope<Statement>.PushResult.Success);  // since we just checked for duplicates, we expect
 03572          if (DominatingStatementLabels.Find(lnode.Name) != null) {
 03573            reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows a dominating label");
 03574          } else {
 03575            var rr = DominatingStatementLabels.Push(lnode.Name, lnode);
 03576            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 03577          }
 03578        }
 03579      }
 4527403580      ResolveStatement(stmt, resolutionContext);
 4527403581      enclosingStatementLabels.PopMarker();
 4527403582    }
 3583
 03584    void ResolveAlternatives(List<GuardedAlternative> alternatives, AlternativeLoopStmt loopToCatchBreaks, ResolutionCon
 3585      Contract.Requires(alternatives != null);
 3586      Contract.Requires(resolutionContext != null);
 3587
 3588      // first, resolve the guards
 03589      foreach (var alternative in alternatives) {
 03590        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 03591        ResolveExpression(alternative.Guard, resolutionContext);
 03592        Contract.Assert(alternative.Guard.Type != null);  // follows from postcondition of ResolveExpression
 03593        bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 03594        ConstrainTypeExprBool(alternative.Guard, "condition is expected to be of type bool, but is {0}");
 03595      }
 3596
 03597      if (loopToCatchBreaks != null) {
 03598        loopStack.Add(loopToCatchBreaks);  // push
 03599      }
 03600      foreach (var alternative in alternatives) {
 03601        scope.PushMarker();
 03602        DominatingStatementLabels.PushMarker();
 03603        if (alternative.IsBindingGuard) {
 03604          var exists = (ExistsExpr)alternative.Guard;
 03605          foreach (var v in exists.BoundVars) {
 03606            ScopePushAndReport(scope, v, "bound-variable");
 03607          }
 03608        }
 03609        ResolveAttributes(alternative, resolutionContext);
 03610        foreach (Statement ss in alternative.Body) {
 03611          ResolveStatementWithLabels(ss, resolutionContext);
 03612        }
 03613        DominatingStatementLabels.PopMarker();
 03614        scope.PopMarker();
 03615      }
 03616      if (loopToCatchBreaks != null) {
 03617        loopStack.RemoveAt(loopStack.Count - 1);  // pop
 03618      }
 03619    }
 3620
 3621    /// <summary>
 3622    /// Resolves the given call statement.
 3623    /// Assumes all LHSs have already been resolved (and checked for mutability).
 3624    /// </summary>
 116503625    void ResolveCallStmt(CallStmt s, ResolutionContext resolutionContext, Type receiverType) {
 3626      Contract.Requires(s != null);
 3627      Contract.Requires(resolutionContext != null);
 116503628      bool isInitCall = receiverType != null;
 3629
 116503630      var callee = s.Method;
 116503631      Contract.Assert(callee != null);  // follows from the invariant of CallStmt
 116503632      if (!isInitCall && callee is Constructor) {
 03633        reporter.Error(MessageSource.Resolver, s, "a constructor is allowed to be called only when an object is being al
 03634      }
 3635
 3636      // resolve left-hand sides (the right-hand sides are resolved below)
 872103637      foreach (var lhs in s.Lhs) {
 174203638        Contract.Assume(lhs.Type != null);  // a sanity check that LHSs have already been resolved
 174203639      }
 3640
 116503641      bool tryToResolve = false;
 116503642      if (callee.Outs.Count != s.Lhs.Count) {
 03643        if (isInitCall) {
 03644          reporter.Error(MessageSource.Resolver, s, "a method called as an initialization method must not have any resul
 03645        } else {
 03646          reporter.Error(MessageSource.Resolver, s, "wrong number of method result arguments (got {0}, expected {1})", s
 03647          tryToResolve = true;
 03648        }
 116503649      } else {
 116503650        if (isInitCall) {
 03651          if (callee.IsStatic) {
 03652            reporter.Error(MessageSource.Resolver, s.Tok, "a method called as an initialization method must not be 'stat
 03653          } else {
 03654            tryToResolve = true;
 03655          }
 116503656        } else if (!callee.IsStatic) {
 03657          if (!scope.AllowInstance && s.Receiver is ThisExpr) {
 3658            // The call really needs an instance, but that instance is given as 'this', which is not
 3659            // available in this context.  For more details, see comment in the resolution of a
 3660            // FunctionCallExpr.
 03661            reporter.Error(MessageSource.Resolver, s.Receiver, "'this' is not allowed in a 'static' context");
 03662          } else if (s.Receiver is StaticReceiverExpr) {
 03663            reporter.Error(MessageSource.Resolver, s.Receiver, "call to instance method requires an instance");
 03664          } else {
 03665            tryToResolve = true;
 03666          }
 116503667        } else {
 116503668          tryToResolve = true;
 116503669        }
 116503670      }
 3671
 233003672      if (tryToResolve) {
 116503673        var typeMap = s.MethodSelect.TypeArgumentSubstitutionsAtMemberDeclaration();
 3674        // resolve arguments
 116503675        ResolveActualParameters(s.Bindings, callee.Ins, s.Tok, callee, resolutionContext, typeMap,
 116503676          callee.IsStatic ? null : s.Receiver);
 3677        // type check the out-parameter arguments (in-parameters were type checked as part of ResolveActualParameters)
 755603678        for (int i = 0; i < callee.Outs.Count && i < s.Lhs.Count; i++) {
 174203679          var outFormal = callee.Outs[i];
 174203680          var it = outFormal.Type;
 174203681          Type st = it.Subst(typeMap);
 174203682          var lhs = s.Lhs[i];
 174203683          var what = GetLocationInformation(outFormal, callee.Outs.Count(), i, "method out-parameter");
 3684
 174203685          AddAssignableConstraint(
 174203686            s.Tok, lhs.Type, st,
 174203687            $"incorrect return type {what} (expected {{1}}, got {{0}})");
 174203688        }
 755603689        for (int i = 0; i < s.Lhs.Count; i++) {
 174203690          var lhs = s.Lhs[i];
 3691          // LHS must denote a mutable field.
 174203692          CheckIsLvalue(lhs.Resolved, resolutionContext);
 174203693        }
 116503694      }
 116503695      if (Contract.Exists(callee.Decreases.Expressions, e => e is WildcardExpr) && !resolutionContext.CodeContext.Allows
 03696        reporter.Error(MessageSource.Resolver, s.Tok, "a call to a possibly non-terminating method is allowed only if th
 03697      }
 116503698    }
 3699
 3700    /// <summary>
 3701    /// Resolve the actual arguments given in "bindings". Then, check that there is exactly one
 3702    /// actual for each formal, and impose assignable constraints.
 3703    /// "typeMap" is applied to the type of each formal.
 3704    /// This method should be called only once. That is, bindings.arguments is required to be null on entry to this meth
 3705    /// </summary>
 3706    void ResolveActualParameters(ActualBindings bindings, List<Formal> formals, IToken callTok, object context, Resoluti
 1789503707      Dictionary<TypeParameter, Type> typeMap, Expression/*?*/ receiver) {
 3708      Contract.Requires(bindings != null);
 3709      Contract.Requires(formals != null);
 3710      Contract.Requires(callTok != null);
 3711      Contract.Requires(context is Method || context is Function || context is DatatypeCtor || context is ArrowType);
 3712      Contract.Requires(typeMap != null);
 3713      Contract.Requires(!bindings.WasResolved);
 3714
 3715      string whatKind;
 3716      string name;
 1906003717      if (context is Method cMethod) {
 116503718        whatKind = cMethod.WhatKind;
 116503719        name = $"{whatKind} '{cMethod.Name}'";
 1868903720      } else if (context is Function cFunction) {
 79403721        whatKind = cFunction.WhatKind;
 79403722        name = $"{whatKind} '{cFunction.Name}'";
 3258103723      } else if (context is DatatypeCtor cCtor) {
 1585103724        whatKind = "datatype constructor";
 1585103725        name = $"{whatKind} '{cCtor.Name}'";
 1593603726      } else {
 8503727        var cArrowType = (ArrowType)context;
 8503728        whatKind = "function application";
 8503729        name = $"function type '{cArrowType}'";
 8503730      }
 3731
 3732      // If all arguments are passed positionally, use simple error messages that talk about the count of arguments.
 5303603733      var onlyPositionalArguments = bindings.ArgumentBindings.TrueForAll(binding => binding.FormalParameterName == null)
 1789503734      var simpleErrorReported = false;
 3579003735      if (onlyPositionalArguments) {
 5303603736        var requiredParametersCount = formals.Count(f => f.DefaultValue == null);
 1789503737        var actualsCounts = bindings.ArgumentBindings.Count;
 1789503738        var sig = "";
 14121303739        for (int i = 0; i < formals.Count; i++) {
 3514103740          sig += (", " + formals[i].Name + ": " + formals[i].Type.ToString());
 3514103741        }
 3153503742        if (formals.Count > 0) {
 1364003743          sig = ": (" + sig[2..] + ")";
 1364003744        }
 3579003745        if (requiredParametersCount <= actualsCounts && actualsCounts <= formals.Count) {
 3746          // the situation is plausible
 1789503747        } else if (requiredParametersCount == formals.Count) {
 3748          // this is the common, classical case of no default parameter values; generate a straightforward error message
 03749          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03750          simpleErrorReported = true;
 03751        } else if (actualsCounts < requiredParametersCount) {
 03752          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03753          simpleErrorReported = true;
 03754        } else {
 03755          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03756          simpleErrorReported = true;
 03757        }
 1789503758      }
 3759
 3760      // resolve given arguments and populate the "namesToActuals" map
 1789503761      var namesToActuals = new Dictionary<string, ActualBinding>();
 5303603762      formals.ForEach(f => namesToActuals.Add(f.Name, null)); // a name mapping to "null" says it hasn't been filled in 
 1789503763      var stillAcceptingPositionalArguments = true;
 1789503764      var bindingIndex = 0;
 15910803765      foreach (var binding in bindings.ArgumentBindings) {
 3514103766        var arg = binding.Actual;
 3767        // insert the actual into "namesToActuals" under an appropriate name, unless there is an error
 3514103768        if (binding.FormalParameterName != null) {
 03769          var pname = binding.FormalParameterName.val;
 03770          stillAcceptingPositionalArguments = false;
 03771          if (!namesToActuals.TryGetValue(pname, out var b)) {
 03772            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the binding named '{pname}' does not c
 03773          } else if (b == null) {
 3774            // all is good
 03775            namesToActuals[pname] = binding;
 03776          } else if (b.FormalParameterName == null) {
 03777            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the parameter named '{pname}' is alrea
 03778          } else {
 03779            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"duplicate binding for parameter name '
 03780          }
 3514103781        } else if (!stillAcceptingPositionalArguments) {
 03782          reporter.Error(MessageSource.Resolver, arg.tok, "a positional argument is not allowed to follow named argument
 7028203783        } else if (bindingIndex < formals.Count) {
 3784          // use the name of formal corresponding to this positional argument, unless the parameter is named-only
 3514103785          var formal = formals[bindingIndex];
 3514103786          var pname = formal.Name;
 3514103787          if (formal.IsNameOnly) {
 03788            reporter.Error(MessageSource.Resolver, arg.tok,
 03789              $"nameonly parameter '{pname}' must be passed using a name binding; it cannot be passed positionally");
 03790          }
 3514103791          Contract.Assert(namesToActuals[pname] == null); // we expect this, since we've only filled parameters position
 3514103792          namesToActuals[pname] = binding;
 3514103793        } else {
 3794          // too many positional arguments
 03795          if (onlyPositionalArguments) {
 3796            // error was reported before the "foreach" loop
 03797            Contract.Assert(simpleErrorReported);
 03798          } else if (formals.Count < bindingIndex) {
 3799            // error was reported on a previous iteration of this "foreach" loop
 03800          } else {
 03801            reporter.Error(MessageSource.Resolver, callTok,
 03802              $"wrong number of arguments ({name} expects {formals.Count}, got {bindings.ArgumentBindings.Count})");
 03803          }
 03804        }
 3805
 3806        // resolve argument
 3514103807        ResolveExpression(arg, resolutionContext);
 3514103808        bindingIndex++;
 3514103809      }
 3810
 1789503811      var actuals = new List<Expression>();
 1789503812      var formalIndex = 0;
 1789503813      var substMap = new Dictionary<IVariable, Expression>();
 15910803814      foreach (var formal in formals) {
 3514103815        var b = namesToActuals[formal.Name];
 7028203816        if (b != null) {
 3514103817          actuals.Add(b.Actual);
 3514103818          substMap.Add(formal, b.Actual);
 3514103819          var what = GetLocationInformation(formal,
 3514103820            bindings.ArgumentBindings.Count(), bindings.ArgumentBindings.IndexOf(b),
 3514103821            whatKind + (context is Method ? " in-parameter" : " parameter"));
 3822
 3514103823          AddAssignableConstraint(
 3514103824            callTok, formal.Type.Subst(typeMap), b.Actual.Type,
 3514103825            $"incorrect argument type {what} (expected {{0}}, found {{1}})");
 3514103826        } else if (formal.DefaultValue != null) {
 3827          // Note, in the following line, "substMap" is passed in, but it hasn't been fully filled in until the
 3828          // end of this foreach loop. Still, that's soon enough, because DefaultValueExpression won't use it
 3829          // until FillInDefaultValueExpressions at the end of Pass 1 of the Resolver.
 03830          var n = new DefaultValueExpression(callTok, formal, receiver, substMap, typeMap);
 03831          allDefaultValueExpressions.Add(n);
 03832          actuals.Add(n);
 03833          substMap.Add(formal, n);
 03834        } else {
 3835          // parameter has no value
 03836          if (onlyPositionalArguments) {
 3837            // a simple error message has already been reported
 03838            Contract.Assert(simpleErrorReported);
 03839          } else {
 03840            var formalDescription = whatKind + (context is Method ? " in-parameter" : " parameter");
 03841            var nameWithIndex = formal.HasName && formal is not ImplicitFormal ? "'" + formal.Name + "'" : "";
 03842            if (formals.Count > 1 || nameWithIndex == "") {
 03843              nameWithIndex += nameWithIndex == "" ? "" : " ";
 03844              nameWithIndex += $"at index {formalIndex}";
 03845            }
 03846            var message = $"{formalDescription} {nameWithIndex} requires an argument of type {formal.Type}";
 03847            reporter.Error(MessageSource.Resolver, callTok, message);
 03848          }
 03849        }
 3514103850        formalIndex++;
 3514103851      }
 3852
 1789503853      bindings.AcceptArgumentExpressionsAsExactParameterList(actuals);
 1789503854    }
 3855
 3688303856    private static string GetLocationInformation(Formal parameter, int bindingCount, int bindingIndex, string formalDesc
 3688303857      var displayName = parameter.HasName && parameter is not ImplicitFormal;
 3688303858      var description = "";
 7292803859      if (bindingCount > 1) {
 3604503860        description += $"at index {bindingIndex} ";
 3604503861      }
 3862
 3688303863      description += $"for {formalDescription}";
 3864
 7356603865      if (displayName) {
 3668303866        description += $" '{parameter.Name}'";
 3668303867      }
 3868
 3688303869      return description;
 3688303870    }
 3871
 3872    /// <summary>
 3873    /// To resolve "id" in expression "E . id", do:
 3874    ///  * If E denotes a module name M:
 3875    ///      0. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 3876    ///         (if two imported types have the same name, an error message is produced here)
 3877    ///      1. Static member of M._default denoting an async task type
 3878    ///    (Note that in contrast to ResolveNameSegment_Type, imported modules, etc. are ignored)
 3879    ///  * If E denotes a type:
 3880    ///      2. a. Member of that type denoting an async task type, or:
 3881    ///         b. If allowDanglingDotName:
 3882    ///            Return the type "E" and the given "expr", letting the caller try to make sense of the final dot-name.
 3883    ///
 3884    /// Note: 1 and 2a are not used now, but they will be of interest when async task types are supported.
 3885    /// </summary>
 03886    ResolveTypeReturn ResolveDotSuffix_Type(ExprDotName expr, ResolutionContext resolutionContext, bool allowDanglingDot
 3887      Contract.Requires(expr != null);
 3888      Contract.Requires(!expr.WasResolved());
 3889      Contract.Requires(expr.Lhs is NameSegment || expr.Lhs is ExprDotName);
 3890      Contract.Requires(resolutionContext != null);
 3891      Contract.Ensures(Contract.Result<ResolveTypeReturn>() == null || allowDanglingDotName);
 3892
 3893      // resolve the LHS expression
 03894      if (expr.Lhs is NameSegment) {
 03895        ResolveNameSegment_Type((NameSegment)expr.Lhs, resolutionContext, option, defaultTypeArguments);
 03896      } else {
 03897        ResolveDotSuffix_Type((ExprDotName)expr.Lhs, resolutionContext, false, option, defaultTypeArguments);
 03898      }
 3899
 03900      if (expr.OptTypeArguments != null) {
 03901        foreach (var ty in expr.OptTypeArguments) {
 03902          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 03903        }
 03904      }
 3905
 03906      Expression r = null;  // the resolved expression, if successful
 3907
 03908      var lhs = expr.Lhs.Resolved;
 03909      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 03910        var ri = (Resolver_IdentifierExpr)lhs;
 03911        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 03912        sig = GetSignature(sig);
 3913        // For 0:
 3914
 03915        if (sig.TopLevels.TryGetValue(expr.SuffixName, out var decl)) {
 3916          // ----- 0. Member of the specified module
 03917          if (decl is AmbiguousTopLevelDecl) {
 03918            var ad = (AmbiguousTopLevelDecl)decl;
 03919            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 03920          } else {
 3921            // We have found a module name or a type name.  We create a temporary expression that will never be seen by 
 3922            // or verifier, just to have a placeholder where we can recorded what we have found.
 03923            r = CreateResolver_IdentifierExpr(expr.tok, expr.SuffixName, expr.OptTypeArguments, decl);
 03924          }
 3925#if ASYNC_TASK_TYPES
 3926        } else if (sig.StaticMembers.TryGetValue(expr.SuffixName, out member)) {
 3927          // ----- 1. static member of the specified module
 3928          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 3929          if (ReallyAmbiguousThing(ref member)) {
 3930            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 3931          } else {
 3932            var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 3933            r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMetho
 3934          }
 3935#endif
 03936        } else {
 03937          reporter.Error(MessageSource.Resolver, expr.tok, "module '{0}' does not declare a type '{1}'", ri.Decl.Name, e
 03938        }
 3939
 03940      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 03941        var ri = (Resolver_IdentifierExpr)lhs;
 3942        // ----- 2. Look up name in type
 03943        var ty = new UserDefinedType(ri.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs);
 03944        if (allowDanglingDotName && ty.IsRefType) {
 03945          return new ResolveTypeReturn(ty, expr);
 3946        }
 03947        if (r == null) {
 03948          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in type '{1}' or cannot be part 
 03949        }
 03950      }
 3951
 03952      if (r == null) {
 3953        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 03954        expr.Type = new InferredTypeProxy();
 03955      } else {
 03956        expr.ResolvedExpression = r;
 03957        expr.Type = r.Type;
 03958      }
 03959      return null;
 03960    }
 3961
 1020803962    internal Resolver_IdentifierExpr CreateResolver_IdentifierExpr(IToken tok, string name, List<Type> optTypeArguments,
 3963      Contract.Requires(tok != null);
 3964      Contract.Requires(name != null);
 3965      Contract.Requires(decl != null);
 3966      Contract.Ensures(Contract.Result<Resolver_IdentifierExpr>() != null);
 3967
 2041603968      if (!moduleInfo.IsAbstract) {
 1020803969        if (decl is ModuleDecl md && md.Signature.IsAbstract) {
 03970          reporter.Error(MessageSource.Resolver, tok, "a compiled module is not allowed to use an abstract module ({0})"
 03971        }
 1020803972      }
 1020803973      var n = optTypeArguments == null ? 0 : optTypeArguments.Count;
 1260253974      if (optTypeArguments != null) {
 3975        // type arguments were supplied; they must be equal in number to those expected
 239453976        if (n != decl.TypeArgs.Count) {
 03977          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}
 03978        }
 239453979      }
 1020803980      List<Type> tpArgs = new List<Type>();
 3817453981      for (int i = 0; i < decl.TypeArgs.Count; i++) {
 591953982        tpArgs.Add(i < n ? optTypeArguments[i] : new InferredTypeProxy());
 591953983      }
 1020803984      return new Resolver_IdentifierExpr(tok, decl, tpArgs);
 1020803985    }
 3986
 8452203987    public void ResolveStatement(Statement stmt, ResolutionContext resolutionContext) {
 3988      Contract.Requires(stmt != null);
 3989      Contract.Requires(resolutionContext != null);
 8907403990      if (stmt is ICanResolve canResolve) {
 455203991        canResolve.Resolve(this, resolutionContext);
 455203992        return;
 3993      }
 15994003994      if (!(stmt is ForallStmt || stmt is ForLoopStmt)) {  // "forall" and "for" statements do their own attribute resol
 7997003995        ResolveAttributes(stmt, resolutionContext);
 7997003996      }
 7997003997      if (stmt is PredicateStmt) {
 03998        PredicateStmt s = (PredicateStmt)stmt;
 03999        var assertStmt = stmt as AssertStmt;
 04000        if (assertStmt != null && assertStmt.Label != null) {
 04001          if (DominatingStatementLabels.Find(assertStmt.Label.Name) != null) {
 04002            reporter.Error(MessageSource.Resolver, assertStmt.Label.Tok, "assert label shadows a dominating label");
 04003          } else {
 04004            var rr = DominatingStatementLabels.Push(assertStmt.Label.Name, assertStmt.Label);
 04005            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 04006          }
 04007        }
 4008
 04009        if (assertStmt != null && Attributes.Find(assertStmt.Attributes, "only") is UserSuppliedAttributes attribute) {
 04010          reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_assumes_others.ToString(), att
 04011            "Assertion with {:only} temporarily transforms other assertions into assumptions");
 04012          if (attribute.Args.Count >= 1
 04013              && attribute.Args[0] is LiteralExpr { Value: string value }
 04014              && value != "before" && value != "after") {
 04015            reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_before_after.ToString(), att
 04016              "{:only} only accepts \"before\" or \"after\" as an optional argument");
 04017          }
 04018        }
 04019        ResolveExpression(s.Expr, resolutionContext);
 04020        Contract.Assert(s.Expr.Type != null);  // follows from postcondition of ResolveExpression
 04021        ConstrainTypeExprBool(s.Expr, "condition is expected to be of type bool, but is {0}");
 04022        if (assertStmt != null && assertStmt.Proof != null) {
 4023          // clear the labels for the duration of checking the proof body, because break statements are not allowed to l
 04024          var prevLblStmts = enclosingStatementLabels;
 04025          var prevLoopStack = loopStack;
 04026          enclosingStatementLabels = new Scope<Statement>(Options);
 04027          loopStack = new List<Statement>();
 04028          ResolveStatement(assertStmt.Proof, resolutionContext);
 04029          enclosingStatementLabels = prevLblStmts;
 04030          loopStack = prevLoopStack;
 04031        }
 04032        var expectStmt = stmt as ExpectStmt;
 04033        if (expectStmt != null) {
 04034          if (expectStmt.Message == null) {
 04035            expectStmt.Message = new StringLiteralExpr(s.Tok, "expectation violation", false);
 04036          }
 04037          ResolveExpression(expectStmt.Message, resolutionContext);
 04038          Contract.Assert(expectStmt.Message.Type != null);  // follows from postcondition of ResolveExpression
 04039        }
 4040
 8386004041      } else if (stmt is PrintStmt) {
 389004042        var s = (PrintStmt)stmt;
 1360404043        s.Args.Iter(e => ResolveExpression(e, resolutionContext));
 4044
 7997004045      } else if (stmt is RevealStmt) {
 04046        var s = (RevealStmt)stmt;
 04047        foreach (var expr in s.Exprs) {
 04048          var name = RevealStmt.SingleName(expr);
 04049          var labeledAssert = name == null ? null : DominatingStatementLabels.Find(name) as AssertLabel;
 04050          if (labeledAssert != null) {
 04051            s.LabeledAsserts.Add(labeledAssert);
 04052          } else {
 04053            var revealResolutionContext = resolutionContext with { InReveal = true };
 04054            if (expr is ApplySuffix) {
 04055              var e = (ApplySuffix)expr;
 04056              var methodCallInfo = ResolveApplySuffix(e, revealResolutionContext, true);
 04057              if (methodCallInfo == null) {
 04058                reporter.Error(MessageSource.Resolver, expr.tok, "expression has no reveal lemma");
 04059              } else if (methodCallInfo.Callee.Member is TwoStateLemma && !revealResolutionContext.IsTwoState) {
 04060                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "a two-state function can only be revealed in
 04061              } else if (methodCallInfo.Callee.AtLabel != null) {
 04062                Contract.Assert(methodCallInfo.Callee.Member is TwoStateLemma);
 04063                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "to reveal a two-state function, do not list 
 04064              } else {
 04065                var call = new CallStmt(s.RangeToken, new List<Expression>(), methodCallInfo.Callee, methodCallInfo.Actu
 04066                s.ResolvedStatements.Add(call);
 04067              }
 04068            } else if (expr is NameSegment or ExprDotName) {
 04069              if (expr is NameSegment) {
 04070                ResolveNameSegment((NameSegment)expr, true, null, revealResolutionContext, true);
 04071              } else {
 04072                ResolveDotSuffix((ExprDotName)expr, true, null, revealResolutionContext, true);
 04073              }
 04074              MemberSelectExpr callee = (MemberSelectExpr)((ConcreteSyntaxExpression)expr).ResolvedExpression;
 04075              if (callee == null) {
 04076              } else if (callee.Member is Lemma or TwoStateLemma && Attributes.Contains(callee.Member.Attributes, "axiom
 4077                //The revealed member is a function
 04078                reporter.Error(MessageSource.Resolver, callee.tok, "to reveal a function ({0}), append parentheses", cal
 04079              } else {
 04080                var call = new CallStmt(s.RangeToken, new List<Expression>(), callee, new List<ActualBinding>(), expr.to
 04081                s.ResolvedStatements.Add(call);
 04082              }
 04083            } else {
 04084              ResolveExpression(expr, revealResolutionContext);
 04085            }
 04086          }
 04087        }
 04088        foreach (var a in s.ResolvedStatements) {
 04089          ResolveStatement(a, resolutionContext);
 04090        }
 7608004091      } else if (stmt is BreakStmt) {
 04092        var s = (BreakStmt)stmt;
 04093        if (s.TargetLabel != null) {
 04094          Statement target = enclosingStatementLabels.Find(s.TargetLabel.val);
 04095          if (target == null) {
 04096            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"{s.Kind} label is undefined or not in scope: {s.Targ
 04097          } else if (s.IsContinue && !(target is LoopStmt)) {
 04098            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"continue label must designate a loop: {s.TargetLabel
 04099          } else {
 04100            s.TargetStmt = target;
 04101          }
 04102        } else {
 04103          Contract.Assert(1 <= s.BreakAndContinueCount); // follows from BreakStmt class invariant and the guard for thi
 04104          var jumpStmt = s.BreakAndContinueCount == 1 ?
 04105            $"a non-labeled '{s.Kind}' statement" :
 04106            $"a '{Util.Repeat(s.BreakAndContinueCount - 1, "break ")}{s.Kind}' statement";
 04107          if (loopStack.Count == 0) {
 04108            reporter.Error(MessageSource.Resolver, s, $"{jumpStmt} is allowed only in loops");
 04109          } else if (loopStack.Count < s.BreakAndContinueCount) {
 04110            reporter.Error(MessageSource.Resolver, s,
 04111              $"{jumpStmt} is allowed only in contexts with {s.BreakAndContinueCount} enclosing loops, but the current c
 04112          } else {
 04113            Statement target = loopStack[loopStack.Count - s.BreakAndContinueCount];
 04114            if (target.Labels == null) {
 4115              // make sure there is a label, because the compiler and translator will want to see a unique ID
 04116              target.Labels = new LList<Label>(new Label(target.Tok, null), null);
 04117            }
 04118            s.TargetStmt = target;
 04119          }
 04120        }
 4121
 7608004122      } else if (stmt is ProduceStmt) {
 04123        var kind = stmt is YieldStmt ? "yield" : "return";
 04124        if (stmt is YieldStmt && !(resolutionContext.CodeContext is IteratorDecl)) {
 04125          reporter.Error(MessageSource.Resolver, stmt, "yield statement is allowed only in iterators");
 04126        } else if (stmt is ReturnStmt && !(resolutionContext.CodeContext is Method)) {
 04127          reporter.Error(MessageSource.Resolver, stmt, "return statement is allowed only in method");
 04128        } else if (resolutionContext.InFirstPhaseConstructor) {
 04129          reporter.Error(MessageSource.Resolver, stmt, "return statement is not allowed before 'new;' in a constructor")
 04130        }
 04131        var s = (ProduceStmt)stmt;
 04132        if (s.Rhss != null) {
 04133          var cmc = resolutionContext.CodeContext as IMethodCodeContext;
 04134          if (cmc == null) {
 4135            // an error has already been reported above
 04136          } else if (cmc.Outs.Count != s.Rhss.Count) {
 04137            reporter.Error(MessageSource.Resolver, s, "number of {2} parameters does not match declaration (found {0}, e
 04138          } else {
 04139            Contract.Assert(s.Rhss.Count > 0);
 4140            // Create a hidden update statement using the out-parameter formals, resolve the RHS, and check that the RHS
 04141            List<Expression> formals = new List<Expression>();
 04142            foreach (Formal f in cmc.Outs) {
 4143              Expression produceLhs;
 04144              if (stmt is ReturnStmt) {
 04145                var ident = new ImplicitIdentifierExpr(f.tok, f.Name);
 4146                // resolve it here to avoid capture into more closely declared local variables
 04147                ident.Var = f;
 04148                ident.Type = ident.Var.Type;
 04149                Contract.Assert(f.Type != null);
 04150                produceLhs = ident;
 04151              } else {
 04152                var yieldIdent = new MemberSelectExpr(f.tok, new ImplicitThisExpr(f.tok), f.Name);
 04153                ResolveExpression(yieldIdent, resolutionContext);
 04154                produceLhs = yieldIdent;
 04155              }
 04156              formals.Add(produceLhs);
 04157            }
 04158            s.HiddenUpdate = new UpdateStmt(s.RangeToken, formals, s.Rhss, true);
 4159            // resolving the update statement will check for return/yield statement specifics.
 04160            ResolveStatement(s.HiddenUpdate, resolutionContext);
 04161          }
 04162        } else {// this is a regular return/yield statement.
 04163          s.HiddenUpdate = null;
 04164        }
 11019104165      } else if (stmt is VarDeclStmt) {
 3411104166        var s = (VarDeclStmt)stmt;
 4167        // We have four cases.
 3411104168        Contract.Assert(s.Update == null || s.Update is AssignSuchThatStmt || s.Update is UpdateStmt || s.Update is Assi
 4169        // 0.  There is no .Update.  This is easy, we will just resolve the locals.
 4170        // 1.  The .Update is an AssignSuchThatStmt.  This is also straightforward:  first
 4171        //     resolve the locals, which adds them to the scope, and then resolve the .Update.
 4172        // 2.  The .Update is an UpdateStmt, which, resolved, means either a CallStmt or a bunch
 4173        //     of parallel AssignStmt's.  Here, the right-hand sides should be resolved before
 4174        //     the local variables have been added to the scope, but the left-hand sides should
 4175        //     resolve to the newly introduced variables.
 4176        // 3.  The .Update is a ":-" statement, for which resolution does two steps:
 4177        //     First, desugar, then run the regular resolution on the desugared AST.
 4178        // To accommodate these options, we first reach into the UpdateStmt, if any, to resolve
 4179        // the left-hand sides of the UpdateStmt.  This will have the effect of shielding them
 4180        // from a subsequent resolution (since expression resolution will do nothing if the .Type
 4181        // field is already assigned.
 4182        // Alright, so it is:
 4183
 4184        // Resolve the types of the locals
 20639704185        foreach (var local in s.Locals) {
 3468804186          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 3468804187          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 6937604188          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 3468804189            local.type = local.OptionalType;
 3468804190          } else {
 04191            local.type = new InferredTypeProxy();
 04192          }
 3468804193        }
 4194        // Resolve the UpdateStmt, if any
 6822204195        if (s.Update is UpdateStmt) {
 3411104196          var upd = (UpdateStmt)s.Update;
 4197          // resolve the LHS
 3411104198          Contract.Assert(upd.Lhss.Count == s.Locals.Count);
 17228604199          for (int i = 0; i < upd.Lhss.Count; i++) {
 3468804200            var local = s.Locals[i];
 3468804201            var lhs = (IdentifierExpr)upd.Lhss[i];  // the LHS in this case will be an IdentifierExpr, because that's ho
 3468804202            Contract.Assert(lhs.Type == null);  // not yet resolved
 3468804203            lhs.Var = local;
 3468804204            lhs.Type = local.Type;
 3468804205          }
 4206          // resolve the whole thing
 3411104207          s.Update.Resolve(this, resolutionContext);
 3411104208        }
 4209
 3411104210        if (s.Update is AssignOrReturnStmt) {
 04211          var assignOrRet = (AssignOrReturnStmt)s.Update;
 4212          // resolve the LHS
 04213          Contract.Assert(assignOrRet.Lhss.Count == s.Locals.Count);
 04214          for (int i = 0; i < s.Locals.Count; i++) {
 04215            var local = s.Locals[i];
 04216            var lhs = (IdentifierExpr)assignOrRet
 04217              .Lhss[i]; // the LHS in this case will be an IdentifierExpr, because that's how the parser creates the Var
 04218            Contract.Assert(lhs.Type == null); // not yet resolved
 04219            lhs.Var = local;
 04220            lhs.Type = local.Type;
 04221          }
 4222
 4223          // resolve the whole thing
 04224          assignOrRet.Resolve(this, resolutionContext);
 04225        }
 4226        // Add the locals to the scope
 20639704227        foreach (var local in s.Locals) {
 3468804228          ScopePushAndReport(scope, local, "local-variable");
 3468804229        }
 4230        // With the new locals in scope, it's now time to resolve the attributes on all the locals
 20639704231        foreach (var local in s.Locals) {
 3468804232          ResolveAttributes(local, resolutionContext);
 3468804233        }
 4234        // Resolve the AssignSuchThatStmt, if any
 3411104235        if (s.Update is AssignSuchThatStmt assignSuchThatStmt) {
 04236          assignSuchThatStmt.Resolve(this, resolutionContext);
 04237        }
 7608004238      } else if (stmt is VarDeclPattern) {
 04239        VarDeclPattern s = (VarDeclPattern)stmt;
 04240        foreach (var local in s.LocalVars) {
 04241          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04242          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04243          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 04244            local.type = local.OptionalType;
 04245          } else {
 04246            local.type = new InferredTypeProxy();
 04247          }
 04248        }
 04249        ResolveExpression(s.RHS, resolutionContext);
 04250        ResolveCasePattern(s.LHS, s.RHS.Type, resolutionContext);
 4251        // Check for duplicate names now, because not until after resolving the case pattern do we know if identifiers i
 04252        var c = 0;
 04253        foreach (var bv in s.LHS.Vars) {
 04254          ScopePushAndReport(scope, bv, "local_variable");
 04255          c++;
 04256        }
 04257        if (c == 0) {
 4258          // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constant li
 04259          reporter.Error(MessageSource.Resolver, s.LHS.tok, "LHS is a constant literal; to be legal, it must introduce a
 04260        }
 7946704261      } else if (stmt is AssignStmt) {
 3749804262        AssignStmt s = (AssignStmt)stmt;
 3749804263        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 3749804264        ResolveExpression(s.Lhs, resolutionContext);  // allow ghosts for now, tighted up below
 3749804265        bool lhsResolvedSuccessfully = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 3749804266        Contract.Assert(s.Lhs.Type != null);  // follows from postcondition of ResolveExpression
 4267        // check that LHS denotes a mutable variable or a field
 3749804268        var lhs = s.Lhs.Resolved;
 7499604269        if (lhs is IdentifierExpr) {
 3749804270          IVariable var = ((IdentifierExpr)lhs).Var;
 3749804271          if (var == null) {
 4272            // the LHS didn't resolve correctly; some error would already have been reported
 3749804273          } else {
 3749804274            CheckIsLvalue(lhs, resolutionContext);
 3749804275          }
 3749804276        } else if (lhs is MemberSelectExpr) {
 04277          var fse = (MemberSelectExpr)lhs;
 04278          if (fse.Member != null) {  // otherwise, an error was reported above
 04279            CheckIsLvalue(fse, resolutionContext);
 04280          }
 04281        } else if (lhs is SeqSelectExpr) {
 04282          var slhs = (SeqSelectExpr)lhs;
 4283          // LHS is fine, provided the "sequence" is really an array
 04284          if (lhsResolvedSuccessfully) {
 04285            Contract.Assert(slhs.Seq.Type != null);
 04286            CheckIsLvalue(slhs, resolutionContext);
 04287          }
 04288        } else if (lhs is MultiSelectExpr) {
 04289          CheckIsLvalue(lhs, resolutionContext);
 04290        } else {
 04291          CheckIsLvalue(lhs, resolutionContext);
 04292        }
 3749804293        Type lhsType = s.Lhs.Type;
 7499604294        if (s.Rhs is ExprRhs) {
 3749804295          ExprRhs rr = (ExprRhs)s.Rhs;
 3749804296          ResolveExpression(rr.Expr, resolutionContext);
 3749804297          Contract.Assert(rr.Expr.Type != null);  // follows from postcondition of ResolveExpression
 4298
 3749804299          if (s.Lhs is ImplicitIdentifierExpr { Var: Formal { InParam: false } }) {
 04300            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "Method return value mismatch (expected {0}, got {1
 3749804301          } else {
 3749804302            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "RHS (of type {1}) not assignable to LHS (of type {
 3749804303          }
 3749804304        } else if (s.Rhs is TypeRhs) {
 04305          TypeRhs rr = (TypeRhs)s.Rhs;
 04306          Type t = ResolveTypeRhs(rr, stmt, resolutionContext);
 04307          AddAssignableConstraint(stmt.Tok, lhsType, t, "type {1} is not assignable to LHS (of type {0})");
 04308        } else if (s.Rhs is HavocRhs) {
 4309          // nothing else to do
 04310        } else {
 04311          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected RHS
 4312        }
 4313
 4313404314      } else if (stmt is CallStmt) {
 116504315        CallStmt s = (CallStmt)stmt;
 116504316        ResolveCallStmt(s, resolutionContext, null);
 4317
 719204318      } else if (stmt is BlockStmt) {
 272104319        var s = (BlockStmt)stmt;
 272104320        scope.PushMarker();
 272104321        ResolveBlockStatement(s, resolutionContext);
 272104322        scope.PopMarker();
 4323
 389104324      } else if (stmt is IfStmt) {
 58504325        IfStmt s = (IfStmt)stmt;
 117004326        if (s.Guard != null) {
 58504327          ResolveExpression(s.Guard, resolutionContext);
 58504328          Contract.Assert(s.Guard.Type != null);  // follows from postcondition of ResolveExpression
 58504329          ConstrainTypeExprBool(s.Guard, "condition is expected to be of type bool, but is {0}");
 58504330        }
 4331
 58504332        scope.PushMarker();
 58504333        if (s.IsBindingGuard) {
 04334          var exists = (ExistsExpr)s.Guard;
 04335          foreach (var v in exists.BoundVars) {
 04336            ScopePushAndReport(scope, v, "bound-variable");
 04337          }
 04338        }
 58504339        DominatingStatementLabels.PushMarker();
 58504340        ResolveBlockStatement(s.Thn, resolutionContext);
 58504341        DominatingStatementLabels.PopMarker();
 58504342        scope.PopMarker();
 4343
 117004344        if (s.Els != null) {
 58504345          DominatingStatementLabels.PushMarker();
 58504346          ResolveStatement(s.Els, resolutionContext);
 58504347          DominatingStatementLabels.PopMarker();
 58504348        }
 4349
 58504350      } else if (stmt is AlternativeStmt) {
 04351        var s = (AlternativeStmt)stmt;
 04352        ResolveAlternatives(s.Alternatives, null, resolutionContext);
 4353
 04354      } else if (stmt is OneBodyLoopStmt) {
 04355        var s = (OneBodyLoopStmt)stmt;
 04356        if (s is WhileStmt whileS && whileS.Guard != null) {
 04357          ResolveExpression(whileS.Guard, resolutionContext);
 04358          Contract.Assert(whileS.Guard.Type != null);  // follows from postcondition of ResolveExpression
 04359          ConstrainTypeExprBool(whileS.Guard, "condition is expected to be of type bool, but is {0}");
 04360        } else if (s is ForLoopStmt forS) {
 04361          var loopIndex = forS.LoopIndex;
 04362          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04363          ResolveType(loopIndex.Tok, loopIndex.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04364          var err = new TypeConstraint.ErrorMsgWithToken(loopIndex.Tok, "index variable is expected to be of an integer 
 04365          ConstrainToIntegerType(loopIndex.Tok, loopIndex.Type, false, err);
 4366
 04367          ResolveExpression(forS.Start, resolutionContext);
 04368          AddAssignableConstraint(forS.Start.tok, forS.LoopIndex.Type, forS.Start.Type, "lower bound (of type {1}) not a
 04369          if (forS.End != null) {
 04370            ResolveExpression(forS.End, resolutionContext);
 04371            AddAssignableConstraint(forS.End.tok, forS.LoopIndex.Type, forS.End.Type, "upper bound (of type {1}) not ass
 04372            if (forS.Decreases.Expressions.Count != 0) {
 04373              reporter.Error(MessageSource.Resolver, forS.Decreases.Expressions[0].tok,
 04374                "a 'for' loop is allowed an explicit 'decreases' clause only if the end-expression is '*'");
 04375            }
 04376          } else if (forS.Decreases.Expressions.Count == 0 && !resolutionContext.CodeContext.AllowsNontermination) {
 4377            // note, the following error message is also emitted elsewhere (if the loop bears a "decreases *")
 04378            reporter.Error(MessageSource.Resolver, forS.Tok,
 04379              "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be p
 04380              " (or you can add a 'decreases' clause to this 'for' loop if you want to prove that it does indeed termina
 04381          }
 4382
 4383          // Create a new scope, add the local to the scope, and resolve the attributes
 04384          scope.PushMarker();
 04385          ScopePushAndReport(scope, loopIndex, "index-variable");
 04386          ResolveAttributes(s, resolutionContext);
 04387        }
 4388
 04389        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4390
 04391        if (s.Body != null) {
 04392          loopStack.Add(s);  // push
 04393          DominatingStatementLabels.PushMarker();
 04394          ResolveStatement(s.Body, resolutionContext);
 04395          DominatingStatementLabels.PopMarker();
 04396          loopStack.RemoveAt(loopStack.Count - 1);  // pop
 04397        }
 4398
 04399        if (s is ForLoopStmt) {
 04400          scope.PopMarker();
 04401        }
 4402
 04403      } else if (stmt is AlternativeLoopStmt) {
 04404        var s = (AlternativeLoopStmt)stmt;
 04405        ResolveAlternatives(s.Alternatives, s, resolutionContext);
 04406        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4407
 04408      } else if (stmt is ForallStmt) {
 04409        var s = (ForallStmt)stmt;
 4410
 04411        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04412        scope.PushMarker();
 04413        foreach (BoundVar v in s.BoundVars) {
 04414          ScopePushAndReport(scope, v, "local-variable");
 04415          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04416        }
 04417        ResolveExpression(s.Range, resolutionContext);
 04418        Contract.Assert(s.Range.Type != null);  // follows from postcondition of ResolveExpression
 04419        ConstrainTypeExprBool(s.Range, "range restriction in forall statement must be of type bool (instead got {0})");
 04420        foreach (var ens in s.Ens) {
 04421          ResolveExpression(ens.E, resolutionContext);
 04422          Contract.Assert(ens.E.Type != null);  // follows from postcondition of ResolveExpression
 04423          ConstrainTypeExprBool(ens.E, "ensures condition is expected to be of type bool, but is {0}");
 04424        }
 4425        // Since the range and postconditions are more likely to infer the types of the bound variables, resolve them
 4426        // first (above) and only then resolve the attributes (below).
 04427        ResolveAttributes(s, resolutionContext);
 4428
 04429        if (s.Body != null) {
 4430          // clear the labels for the duration of checking the body, because break statements are not allowed to leave a
 04431          var prevLblStmts = enclosingStatementLabels;
 04432          var prevLoopStack = loopStack;
 04433          enclosingStatementLabels = new Scope<Statement>(Options);
 04434          loopStack = new List<Statement>();
 04435          ResolveStatement(s.Body, resolutionContext);
 04436          enclosingStatementLabels = prevLblStmts;
 04437          loopStack = prevLoopStack;
 04438        }
 04439        scope.PopMarker();
 4440
 04441        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 4442          // determine the Kind and run some additional checks on the body
 04443          if (s.Ens.Count != 0) {
 4444            // The only supported kind with ensures clauses is Proof.
 04445            s.Kind = ForallStmt.BodyKind.Proof;
 04446          } else {
 4447            // There are three special cases:
 4448            // * Assign, which is the only kind of the forall statement that allows a heap update.
 4449            // * Call, which is a single call statement with no side effects or output parameters.
 4450            // * A single calc statement, which is a special case of Proof where the postcondition can be inferred.
 4451            // The effect of Assign and the postcondition of Call will be seen outside the forall
 4452            // statement.
 04453            Statement s0 = s.S0;
 04454            if (s0 is AssignStmt) {
 04455              s.Kind = ForallStmt.BodyKind.Assign;
 4456
 04457              var rhs = ((AssignStmt)s0).Rhs;
 04458              if (rhs is TypeRhs) {
 04459                reporter.Error(MessageSource.Resolver, rhs.Tok, "new allocation not supported in aggregate assignments")
 04460              }
 4461
 04462            } else if (s0 is CallStmt) {
 04463              s.Kind = ForallStmt.BodyKind.Call;
 04464              var call = (CallStmt)s.S0;
 04465              var method = call.Method;
 4466              // if the called method is not in the same module as the ForallCall stmt
 4467              // don't convert it to ForallExpression since the inlined called method's
 4468              // ensure clause might not be resolved correctly(test\dafny3\GenericSort.dfy)
 04469              if (method.EnclosingClass.EnclosingModuleDefinition != resolutionContext.CodeContext.EnclosingModule) {
 04470                s.CanConvert = false;
 04471              }
 4472              // Additional information (namely, the postcondition of the call) will be reported later. But it cannot be
 4473              // done yet, because the specification of the callee may not have been resolved yet.
 04474            } else if (s0 is CalcStmt) {
 04475              s.Kind = ForallStmt.BodyKind.Proof;
 4476              // add the conclusion of the calc as a free postcondition
 04477              var result = ((CalcStmt)s0).Result;
 04478              s.Ens.Add(new AttributedExpression(result));
 04479              reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(Options, result));
 04480            } else {
 04481              s.Kind = ForallStmt.BodyKind.Proof;
 04482              if (s.Body is BlockStmt && ((BlockStmt)s.Body).Body.Count == 0) {
 4483                // an empty statement, so don't produce any warning
 04484              } else {
 04485                reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, s.Tok, "the conclusion of the body of thi
 04486              }
 04487            }
 04488          }
 4489
 04490          if (s.ForallExpressions != null) {
 04491            foreach (Expression expr in s.ForallExpressions) {
 04492              ResolveExpression(expr, resolutionContext);
 04493            }
 04494          }
 04495        }
 4496
 04497      } else if (stmt is ModifyStmt) {
 04498        var s = (ModifyStmt)stmt;
 04499        ResolveAttributes(s.Mod, resolutionContext);
 04500        foreach (FrameExpression fe in s.Mod.Expressions) {
 04501          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04502        }
 04503        if (s.Body != null) {
 04504          ResolveBlockStatement(s.Body, resolutionContext);
 04505        }
 4506
 04507      } else if (stmt is CalcStmt) {
 04508        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04509        CalcStmt s = (CalcStmt)stmt;
 4510        // figure out s.Op
 04511        Contract.Assert(s.Op == null);  // it hasn't been set yet
 04512        if (s.UserSuppliedOp != null) {
 04513          s.Op = s.UserSuppliedOp;
 04514        } else {
 04515          s.Op = s.GetInferredDefaultOp() ?? CalcStmt.DefaultOp;
 04516          reporter.Info(MessageSource.Resolver, s.Tok, s.Op.ToString());
 04517        }
 4518
 04519        if (s.Lines.Count > 0) {
 04520          Type lineType = new InferredTypeProxy();
 04521          var e0 = s.Lines.First();
 04522          ResolveExpression(e0, resolutionContext);
 04523          Contract.Assert(e0.Type != null);  // follows from postcondition of ResolveExpression
 04524          var err = new TypeConstraint.ErrorMsgWithToken(e0.tok, "all lines in a calculation must have the same type (go
 04525          ConstrainSubtypeRelation(lineType, e0.Type, err);
 04526          for (int i = 1; i < s.Lines.Count; i++) {
 04527            var e1 = s.Lines[i];
 04528            ResolveExpression(e1, resolutionContext);
 04529            Contract.Assert(e1.Type != null);  // follows from postcondition of ResolveExpression
 4530            // reuse the error object if we're on the dummy line; this prevents a duplicate error message
 04531            if (i < s.Lines.Count - 1) {
 04532              err = new TypeConstraint.ErrorMsgWithToken(e1.tok, "all lines in a calculation must have the same type (go
 04533            }
 04534            ConstrainSubtypeRelation(lineType, e1.Type, err);
 04535            var step = (s.StepOps[i - 1] ?? s.Op).StepExpr(e0, e1); // Use custom line operator
 04536            ResolveExpression(step, resolutionContext);
 04537            s.Steps.Add(step);
 04538            e0 = e1;
 04539          }
 4540
 4541          // clear the labels for the duration of checking the hints, because break statements are not allowed to leave 
 04542          var prevLblStmts = enclosingStatementLabels;
 04543          var prevLoopStack = loopStack;
 04544          enclosingStatementLabels = new Scope<Statement>(Options);
 04545          loopStack = new List<Statement>();
 04546          foreach (var h in s.Hints) {
 04547            foreach (var oneHint in h.Body) {
 04548              DominatingStatementLabels.PushMarker();
 04549              ResolveStatement(oneHint, resolutionContext);
 04550              DominatingStatementLabels.PopMarker();
 04551            }
 04552          }
 04553          enclosingStatementLabels = prevLblStmts;
 04554          loopStack = prevLoopStack;
 4555
 04556        }
 04557        if (prevErrorCount == reporter.Count(ErrorLevel.Error) && s.Lines.Count > 0) {
 4558          // do not build Result from the lines if there were errors, as it might be ill-typed and produce unnecessary r
 04559          var resultOp = s.StepOps.Aggregate(s.Op, (op0, op1) => op1 == null ? op0 : op0.ResultOp(op1));
 04560          s.Result = resultOp.StepExpr(s.Lines.First(), s.Lines.Last());
 04561        } else {
 04562          s.Result = CalcStmt.DefaultOp.StepExpr(Expression.CreateIntLiteral(s.Tok, 0), Expression.CreateIntLiteral(s.To
 04563        }
 04564        ResolveExpression(s.Result, resolutionContext);
 04565        Contract.Assert(s.Result != null);
 04566        Contract.Assert(prevErrorCount != reporter.Count(ErrorLevel.Error) || s.Steps.Count == s.Hints.Count);
 4567
 04568      } else if (stmt is SkeletonStatement) {
 04569        var s = (SkeletonStatement)stmt;
 04570        reporter.Error(MessageSource.Resolver, s.Tok, "skeleton statements are allowed only in refining methods");
 4571        // nevertheless, resolve the underlying statement; hey, why not
 04572        if (s.S != null) {
 04573          ResolveStatement(s.S, resolutionContext);
 04574        }
 04575      } else {
 04576        Contract.Assert(false); throw new cce.UnreachableException();
 4577      }
 8452204578    }
 4579
 4580    private void ResolveLoopSpecificationComponents(List<AttributedExpression> invariants, Specification<Expression> dec
 04581      Specification<FrameExpression> modifies, ResolutionContext resolutionContext) {
 4582      Contract.Requires(invariants != null);
 4583      Contract.Requires(decreases != null);
 4584      Contract.Requires(modifies != null);
 4585      Contract.Requires(resolutionContext != null);
 4586
 04587      foreach (AttributedExpression inv in invariants) {
 04588        ResolveAttributes(inv, resolutionContext);
 04589        ResolveExpression(inv.E, resolutionContext);
 04590        Contract.Assert(inv.E.Type != null);  // follows from postcondition of ResolveExpression
 04591        ConstrainTypeExprBool(inv.E, "invariant is expected to be of type bool, but is {0}");
 04592      }
 4593
 04594      ResolveAttributes(decreases, resolutionContext);
 04595      foreach (Expression e in decreases.Expressions) {
 04596        ResolveExpression(e, resolutionContext);
 04597        if (e is WildcardExpr && !resolutionContext.CodeContext.AllowsNontermination) {
 04598          reporter.Error(MessageSource.Resolver, e, "a possibly infinite loop is allowed only if the enclosing method is
 04599        }
 4600        // any type is fine
 04601      }
 4602
 04603      ResolveAttributes(modifies, resolutionContext);
 04604      if (modifies.Expressions != null) {
 04605        foreach (FrameExpression fe in modifies.Expressions) {
 04606          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04607        }
 04608      }
 04609    }
 4610
 4611    /// <summary>
 4612    /// Resolves the default-valued expression for each formal in "formals".
 4613    /// Solves the resulting type constraints.
 4614    /// Assumes these are the only type constraints to be solved.
 4615    ///
 4616    /// Reports an error for any cyclic dependency among the default-value expressions of the formals.
 4617    /// </summary>
 188504618    public void ResolveParameterDefaultValues(List<Formal> formals, ResolutionContext resolutionContext) {
 4619      Contract.Requires(formals != null);
 4620      Contract.Requires(resolutionContext != null);
 4621
 188504622      Contract.Assume(AllTypeConstraints.Count == 0);
 4623
 4624      // Formal parameters have three ways to indicate how they are to be passed in:
 4625      //   * nameonly: the only way to give a specific argument value is to name the parameter
 4626      //   * positional only: these are nameless parameters (which are allowed only for datatype constructor parameters)
 4627      //   * either positional or by name: this is the most common parameter
 4628      // A parameter is either required or optional:
 4629      //   * required: a caller has to supply an argument
 4630      //   * optional: the parameter has a default value that is used if a caller omits passing a specific argument
 4631      //
 4632      // The syntax for giving a positional-only (i.e., nameless) parameter does not allow a default-value expression, s
 4633      // a positional-only parameter is always required.
 4634      //
 4635      // At a call site, positional arguments are not allowed to follow named arguments. Therefore, if "x" is
 4636      // a nameonly parameter, then there is no way to supply the parameters after "x" by position. Thus, any
 4637      // parameter that follows "x" must either be passed by name or have a default value. That is, if a later
 4638      // parameter does not have a default value, it is _effectively_ nameonly. We impose the rule that
 4639      //   * an effectively nameonly parameter must be declared as nameonly
 4640      //
 4641      // For a positional-only parameter "x", every parameter preceding "x" is _effectively_ required. We impose
 4642      // the rule that
 4643      //   * an effectively required parameter must not have a default-value expression
 188504644      var dependencies = new Graph<IVariable>();
 188504645      string nameOfMostRecentNameonlyParameter = null;
 188504646      var previousParametersWithDefaultValue = new HashSet<Formal>();
 1944004647      foreach (var formal in formals) {
 459504648        if (!formal.HasName) {
 04649          foreach (var previousFormal in previousParametersWithDefaultValue) {
 04650            reporter.Error(MessageSource.Resolver, previousFormal.DefaultValue.tok,
 04651              $"because of a later nameless parameter, this default value is never used; remove it or name all subsequen
 04652          }
 04653          previousParametersWithDefaultValue.Clear();
 04654        }
 459504655        var d = formal.DefaultValue;
 459504656        if (d != null) {
 04657          ResolveExpression(d, resolutionContext);
 04658          AddAssignableConstraint(d.tok, formal.Type, d.Type, "default-value expression (of type '{1}') is not assignabl
 04659          foreach (var v in FreeVariables(d)) {
 04660            dependencies.AddEdge(formal, v);
 04661          }
 04662          previousParametersWithDefaultValue.Add(formal);
 459504663        } else if (nameOfMostRecentNameonlyParameter != null && !formal.IsNameOnly) {
 4664          // "formal" is preceded by a nameonly parameter, but itself is neither nameonly nor has a default value
 04665          reporter.Error(MessageSource.Resolver, formal.tok,
 04666            $"this parameter is effectively nameonly (because of the earlier nameonly parameter '{nameOfMostRecentNameon
 04667            "declare it as nameonly or give it a default-value expression");
 04668        }
 459504669        if (formal.IsNameOnly) {
 04670          nameOfMostRecentNameonlyParameter = formal.Name;
 04671        }
 459504672      }
 188504673      SolveAllTypeConstraints();
 4674
 565504675      foreach (var cycle in dependencies.AllCycles()) {
 04676        var cy = Util.Comma(" -> ", cycle, v => v.Name) + " -> " + cycle[0].Name;
 04677        reporter.Error(MessageSource.Resolver, cycle[0], $"default-value expressions for parameters contain a cycle: {cy
 04678      }
 188504679    }
 4680
 4681    /// <summary>
 4682    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4683    /// </summary>
 4585504684    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOptionEnum eopt, List
 4685      Contract.Requires(tok != null);
 4686      Contract.Requires(type != null);
 4687      Contract.Requires(resolutionContext != null);
 4688      Contract.Requires(eopt != ResolveTypeOptionEnum.AllowPrefixExtend);
 4585504689      ResolveType(tok, type, resolutionContext, new ResolveTypeOption(eopt), defaultTypeArguments);
 4585504690    }
 4691
 8904692    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOptionEnum eopt, List<TypePa
 8904693      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), eopt, defaultTypeArguments);
 8904694    }
 4695
 678104696    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOption option, List<TypePara
 678104697      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), option, defaultTypeArguments);
 678104698    }
 4699
 6503454700    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 4701      Contract.Requires(tok != null);
 4702      Contract.Requires(type != null);
 4703      Contract.Requires(resolutionContext != null);
 4704      Contract.Requires(option != null);
 4705      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6503454706      var r = ResolveTypeLenient(tok, type, resolutionContext, option, defaultTypeArguments, false);
 6503454707      Contract.Assert(r == null);
 6503454708    }
 4709
 4710    public class ResolveTypeReturn {
 4711      public readonly Type ReplacementType;
 4712      public readonly ExprDotName LastComponent;
 04713      public ResolveTypeReturn(Type replacementType, ExprDotName lastComponent) {
 4714        Contract.Requires(replacementType != null);
 4715        Contract.Requires(lastComponent != null);
 04716        ReplacementType = replacementType;
 04717        LastComponent = lastComponent;
 04718      }
 4719    }
 4720    /// <summary>
 4721    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4722    /// One more thing:  if "allowDanglingDotName" is true, then if the resolution would have produced
 4723    ///   an error message that could have been avoided if "type" denoted an identifier sequence one
 4724    ///   shorter, then return an unresolved replacement type where the identifier sequence is one
 4725    ///   shorter.  (In all other cases, the method returns null.)
 4726    /// </summary>
 6503454727    public ResolveTypeReturn ResolveTypeLenient(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeO
 4728      Contract.Requires(tok != null);
 4729      Contract.Requires(type != null);
 4730      Contract.Requires(resolutionContext != null);
 4731      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6503454732      if (type is BitvectorType) {
 04733        var t = (BitvectorType)type;
 4734        // nothing to resolve, but record the fact that this bitvector width is in use
 04735        builtIns.Bitwidths.Add(t.Width);
 7547554736      } else if (type is BasicType) {
 4737        // nothing to resolve
 6503454738      } else if (type is MapType) {
 04739        var mt = (MapType)type;
 04740        var errorCount = reporter.Count(ErrorLevel.Error);
 4741        int typeArgumentCount;
 04742        if (mt.HasTypeArg()) {
 04743          ResolveType(tok, mt.Domain, resolutionContext, option, defaultTypeArguments);
 04744          ResolveType(tok, mt.Range, resolutionContext, option, defaultTypeArguments);
 04745          typeArgumentCount = 2;
 04746        } else if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 04747          mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04748          typeArgumentCount = 0;
 04749        } else {
 04750          var inferredTypeArgs = new List<Type>();
 04751          FillInTypeArguments(tok, 2, inferredTypeArgs, defaultTypeArguments, option);
 04752          Contract.Assert(inferredTypeArgs.Count <= 2);
 04753          if (inferredTypeArgs.Count == 1) {
 04754            mt.SetTypeArgs(inferredTypeArgs[0], new InferredTypeProxy());
 04755            typeArgumentCount = 1;
 04756          } else if (inferredTypeArgs.Count == 2) {
 04757            mt.SetTypeArgs(inferredTypeArgs[0], inferredTypeArgs[1]);
 04758            typeArgumentCount = 2;
 04759          } else {
 04760            mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04761            typeArgumentCount = 0;
 04762          }
 04763        }
 4764        // defaults and auto have been applied; check if we now have the right number of arguments
 04765        if (2 != typeArgumentCount) {
 04766          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of 2) passed to type:
 04767        }
 6097954768      } else if (type is CollectionType) {
 638604769        var t = (CollectionType)type;
 638604770        var errorCount = reporter.Count(ErrorLevel.Error);
 1277204771        if (t.HasTypeArg()) {
 638604772          ResolveType(tok, t.Arg, resolutionContext, option, defaultTypeArguments);
 638604773        } else if (option.Opt != ResolveTypeOptionEnum.DontInfer) {
 04774          var inferredTypeArgs = new List<Type>();
 04775          FillInTypeArguments(tok, 1, inferredTypeArgs, defaultTypeArguments, option);
 04776          if (inferredTypeArgs.Count != 0) {
 04777            Contract.Assert(inferredTypeArgs.Count == 1);
 04778            t.SetTypeArg(inferredTypeArgs[0]);
 04779          }
 04780        }
 638604781        if (!t.HasTypeArg()) {
 4782          // defaults and auto have been applied; check if we now have the right number of arguments
 04783          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments (0 instead of 1) passed to type: {
 4784          // add a proxy type, to make sure that CollectionType will have have a non-null Arg
 04785          t.SetTypeArg(new InferredTypeProxy());
 04786        }
 4787
 6662604788      } else if (type is UserDefinedType) {
 1203254789        var t = (UserDefinedType)type;
 1207704790        if (t.ResolvedClass != null) {
 4791          // Apparently, this type has already been resolved
 4454792          return null;
 4793        }
 1198804794        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 1198804795        if (t.NamePath is ExprDotName) {
 04796          var ret = ResolveDotSuffix_Type((ExprDotName)t.NamePath, resolutionContext, allowDanglingDotName, option, defa
 04797          if (ret != null) {
 04798            return ret;
 4799          }
 1198804800        } else {
 1198804801          var s = (NameSegment)t.NamePath;
 1198804802          ResolveNameSegment_Type(s, resolutionContext, option, defaultTypeArguments);
 1198804803        }
 2397604804        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 1198804805          var r = t.NamePath.Resolved as Resolver_IdentifierExpr;
 1198804806          if (r == null || !(r.Type is Resolver_IdentifierExpr.ResolverType_Type)) {
 04807            reporter.Error(MessageSource.Resolver, t.tok, "expected type");
 2397604808          } else if (r.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 1198804809            var d = r.Decl;
 1198804810            if (d is AbstractTypeDecl) {
 4811              // resolve like a type parameter, and it may have type parameters if it's an abstract type
 04812              t.ResolvedClass = d;  // Store the decl, so the compiler will generate the fully qualified name
 1865604813            } else if (d is RedirectingTypeDecl) {
 666804814              var dd = (RedirectingTypeDecl)d;
 666804815              var caller = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) as ICallable;
 1324704816              if (caller != null && !(d is SubsetTypeDecl && caller is SpecialFunction)) {
 1315804817                if (caller != d) {
 657904818                } else if (d is TypeSynonymDecl && !(d is SubsetTypeDecl)) {
 4819                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04820                  reporter.Error(MessageSource.Resolver, d.tok, "type-synonym cycle: {0} -> {0}", d.Name);
 04821                } else {
 4822                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04823                  reporter.Error(MessageSource.Resolver, d.tok, "recursive constraint dependency involving a {0}: {1} ->
 04824                }
 657904825              }
 666804826              t.ResolvedClass = d;
 1543904827            } else if (d is DatatypeDecl) {
 345104828              t.ResolvedClass = d;
 532004829            } else {
 4830              // d is a type parameter, coinductive datatype, or class, and it may have type parameters
 186904831              t.ResolvedClass = d;
 186904832            }
 1826104833            if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 4834              // don't add anything
 1198804835            } else if (d.TypeArgs.Count != t.TypeArgs.Count && t.TypeArgs.Count == 0) {
 04836              FillInTypeArguments(t.tok, d.TypeArgs.Count, t.TypeArgs, defaultTypeArguments, option);
 04837            }
 4838            // defaults and auto have been applied; check if we now have the right number of arguments
 1198804839            if (d.TypeArgs.Count != t.TypeArgs.Count) {
 04840              reporter.Error(MessageSource.Resolver, t.tok, "Wrong number of type arguments ({0} instead of {1}) passed 
 04841            }
 4842
 1198804843          }
 1198804844        }
 1198804845        if (t.ResolvedClass == null) {
 4846          // There was some error. Still, we will set .ResolvedClass to some value to prevent some crashes in the downst
 4847          // 0-tuple is convenient, because it is always in scope.
 04848          t.ResolvedClass = builtIns.TupleType(t.tok, 0, false);
 4849          // clear out the TypeArgs since 0-tuple doesn't take TypeArg
 04850          t.TypeArgs = new List<Type>();
 04851        }
 4852
 8424904853      } else if (type is TypeProxy) {
 3608604854        TypeProxy t = (TypeProxy)type;
 3608604855        if (t.T != null) {
 04856          ResolveType(tok, t.T, resolutionContext, option, defaultTypeArguments);
 04857        }
 3626404858      } else if (type is SelfType) {
 4859        // do nothing.
 8904860      } else {
 04861        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4862      }
 6499004863      return null;
 6503454864    }
 4865
 4866    /// <summary>
 4867    /// Adds to "typeArgs" a list of "n" type arguments, possibly extending "defaultTypeArguments".
 4868    /// </summary>
 04869    static void FillInTypeArguments(IToken tok, int n, List<Type> typeArgs, List<TypeParameter> defaultTypeArguments, Re
 4870      Contract.Requires(tok != null);
 4871      Contract.Requires(0 <= n);
 4872      Contract.Requires(typeArgs != null && typeArgs.Count == 0);
 04873      if (option.Opt == ResolveTypeOptionEnum.InferTypeProxies) {
 4874        // add type arguments that will be inferred
 04875        for (int i = 0; i < n; i++) {
 04876          typeArgs.Add(new InferredTypeProxy());
 04877        }
 04878      } else if (option.Opt == ResolveTypeOptionEnum.AllowPrefix && defaultTypeArguments.Count < n) {
 4879        // there aren't enough default arguments, so don't do anything
 04880      } else {
 4881        // we'll add arguments
 04882        if (option.Opt == ResolveTypeOptionEnum.AllowPrefixExtend) {
 4883          // extend defaultTypeArguments, if needed
 04884          for (int i = defaultTypeArguments.Count; i < n; i++) {
 04885            var tp = new TypeParameter(tok.ToRange(), new Name(tok.ToRange(), "_T" + i), i, option.Parent);
 04886            if (option.Parent is IteratorDecl) {
 04887              tp.Characteristics.AutoInit = Type.AutoInitInfo.CompilableValue;
 04888            }
 04889            defaultTypeArguments.Add(tp);
 04890          }
 04891        }
 04892        Contract.Assert(n <= defaultTypeArguments.Count);
 4893        // automatically supply a prefix of the arguments from defaultTypeArguments
 04894        for (int i = 0; i < n; i++) {
 04895          typeArgs.Add(new UserDefinedType(defaultTypeArguments[i]));
 04896        }
 04897      }
 04898    }
 4899
 8904900    public static bool TypeConstraintsIncludeProxy(Type t, TypeProxy proxy) {
 8904901      return TypeConstraintsIncludeProxy_Aux(t, proxy, new HashSet<TypeProxy>());
 8904902    }
 13354903    static bool TypeConstraintsIncludeProxy_Aux(Type t, TypeProxy proxy, ISet<TypeProxy> visited) {
 4904      Contract.Requires(t != null);
 4905      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);  // t is expected to have been normalized first
 4906      Contract.Requires(proxy != null && proxy.T == null);
 4907      Contract.Requires(visited != null);
 13354908      var tproxy = t as TypeProxy;
 13354909      if (tproxy != null) {
 04910        if (object.ReferenceEquals(tproxy, proxy)) {
 04911          return true;
 04912        } else if (visited.Contains(tproxy)) {
 04913          return false;
 4914        }
 04915        visited.Add(tproxy);
 04916        foreach (var su in tproxy.Subtypes) {
 04917          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04918            return true;
 4919          }
 04920        }
 04921        foreach (var su in tproxy.Supertypes) {
 04922          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04923            return true;
 4924          }
 04925        }
 13354926      } else {
 4927        // check type arguments of t
 53404928        foreach (var ta in t.TypeArgs) {
 4454929          var a = ta.Normalize();
 4454930          if (TypeConstraintsIncludeProxy_Aux(a, proxy, visited)) {
 04931            return true;
 4932          }
 4454933        }
 13354934      }
 13354935      return false;
 13354936    }
 4937
 04938    public Type ResolveTypeRhs(TypeRhs rr, Statement stmt, ResolutionContext resolutionContext) {
 4939      Contract.Requires(rr != null);
 4940      Contract.Requires(stmt != null);
 4941      Contract.Requires(resolutionContext != null);
 4942      Contract.Ensures(Contract.Result<Type>() != null);
 4943
 04944      if (rr.Type == null) {
 04945        if (rr.ArrayDimensions != null) {
 4946          // ---------- new T[EE]    OR    new T[EE] (elementInit)
 04947          Contract.Assert(rr.Bindings == null && rr.Path == null && rr.InitCall == null);
 04948          ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04949          int i = 0;
 04950          foreach (Expression dim in rr.ArrayDimensions) {
 04951            Contract.Assert(dim != null);
 04952            ResolveExpression(dim, resolutionContext);
 04953            ConstrainToIntegerType(dim, false, string.Format("new must use an integer-based expression for the array siz
 04954            i++;
 04955          }
 04956          rr.Type = ResolvedArrayType(stmt.Tok, rr.ArrayDimensions.Count, rr.EType, resolutionContext, false);
 04957          if (rr.ElementInit != null) {
 04958            ResolveExpression(rr.ElementInit, resolutionContext);
 4959            // Check
 4960            //     int^N -> rr.EType  :>  rr.ElementInit.Type
 04961            builtIns.CreateArrowTypeDecl(rr.ArrayDimensions.Count);  // TODO: should this be done already in the parser?
 04962            var args = new List<Type>();
 04963            for (int ii = 0; ii < rr.ArrayDimensions.Count; ii++) {
 04964              args.Add(builtIns.Nat());
 04965            }
 04966            var arrowType = new ArrowType(rr.ElementInit.tok, builtIns.ArrowTypeDecls[rr.ArrayDimensions.Count], args, r
 04967            var lambdaType = rr.ElementInit.Type.AsArrowType;
 04968            if (lambdaType != null && lambdaType.TypeArgs[0] is InferredTypeProxy) {
 04969              (lambdaType.TypeArgs[0] as InferredTypeProxy).KeepConstraints = true;
 04970            }
 4971            string underscores;
 04972            if (rr.ArrayDimensions.Count == 1) {
 04973              underscores = "_";
 04974            } else {
 04975              underscores = "(" + Util.Comma(rr.ArrayDimensions.Count, x => "_") + ")";
 04976            }
 04977            var hintString = string.Format(" (perhaps write '{0} =>' in front of the expression you gave in order to mak
 04978            ConstrainSubtypeRelation(arrowType, rr.ElementInit.Type, rr.ElementInit, "array-allocation initialization ex
 04979              arrowType, rr.ElementInit.Type, new LazyString_OnTypeEquals(rr.EType, rr.ElementInit.Type, hintString));
 04980          } else if (rr.InitDisplay != null) {
 04981            foreach (var v in rr.InitDisplay) {
 04982              ResolveExpression(v, resolutionContext);
 04983              AddAssignableConstraint(v.tok, rr.EType, v.Type, "initial value must be assignable to array's elements (ex
 04984            }
 04985          }
 04986        } else {
 04987          bool callsConstructor = false;
 04988          if (rr.Bindings == null) {
 04989            ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04990            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 04991            if (cl != null && !(rr.EType.IsTraitType && !rr.EType.NormalizeExpand().IsObjectQ)) {
 4992              // life is good
 04993            } else {
 04994              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 04995            }
 04996          } else {
 04997            string initCallName = null;
 04998            IToken initCallTok = null;
 4999            // Resolve rr.Path and do one of three things:
 5000            // * If rr.Path denotes a type, then set EType,initCallName to rr.Path,"_ctor", which sets up a call to the 
 5001            // * If the all-but-last components of rr.Path denote a type, then do EType,initCallName := allButLast(EType
 5002            // * Otherwise, report an error
 05003            var ret = ResolveTypeLenient(rr.Tok, rr.Path, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum
 05004            if (ret != null) {
 5005              // The all-but-last components of rr.Path denote a type (namely, ret.ReplacementType).
 05006              rr.EType = ret.ReplacementType;
 05007              initCallName = ret.LastComponent.SuffixName;
 05008              initCallTok = ret.LastComponent.tok;
 05009            } else {
 5010              // Either rr.Path resolved correctly as a type or there was no way to drop a last component to make it int
 5011              // like a type.  In either case, set EType,initCallName to Path,"_ctor" and continue.
 05012              rr.EType = rr.Path;
 05013              initCallName = "_ctor";
 05014              initCallTok = rr.Tok;
 05015            }
 05016            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 05017            if (cl == null || rr.EType.IsTraitType) {
 05018              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 05019            } else {
 5020              // ---------- new C.Init(EE)
 05021              Contract.Assert(initCallName != null);
 05022              var prevErrorCount = reporter.Count(ErrorLevel.Error);
 5023
 5024              // We want to create a MemberSelectExpr for the initializing method.  To do that, we create a throw-away r
 5025              // type, create a dot-suffix expression around this receiver, and then resolve it in the usual way for dot
 05026              var lhs = new ImplicitThisExpr_ConstructorCall(initCallTok) { Type = rr.EType };
 05027              var callLhs = new ExprDotName(((UserDefinedType)rr.EType).tok, lhs, initCallName, ret == null ? null : ret
 05028              ResolveDotSuffix(callLhs, true, rr.Bindings.ArgumentBindings, resolutionContext, true);
 05029              if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05030                Contract.Assert(callLhs.ResolvedExpression is MemberSelectExpr);  // since ResolveApplySuffix succeeded 
 05031                var methodSel = (MemberSelectExpr)callLhs.ResolvedExpression;
 05032                if (methodSel.Member is Method) {
 05033                  rr.InitCall = new CallStmt(stmt.RangeToken, new List<Expression>(), methodSel, rr.Bindings.ArgumentBin
 05034                  ResolveCallStmt(rr.InitCall, resolutionContext, rr.EType);
 05035                  if (rr.InitCall.Method is Constructor) {
 05036                    callsConstructor = true;
 05037                  }
 05038                } else {
 05039                  reporter.Error(MessageSource.Resolver, initCallTok, "object initialization must denote an initializing
 05040                }
 05041              }
 05042            }
 05043          }
 05044          if (rr.EType.IsRefType) {
 05045            var udt = rr.EType.NormalizeExpand() as UserDefinedType;
 05046            if (udt != null) {
 05047              var cl = (ClassDecl)udt.ResolvedClass;  // cast is guaranteed by the call to rr.EType.IsRefType above, tog
 05048              if (!callsConstructor && !cl.IsObjectTrait && !udt.IsArrayType && (cl.HasConstructor || cl.EnclosingModule
 05049                reporter.Error(MessageSource.Resolver, stmt, "when allocating an object of {1}type '{0}', one of its con
 05050                  cl.HasConstructor ? "" : "imported ");
 05051              }
 05052            }
 05053          }
 05054          rr.Type = rr.EType;
 05055        }
 05056      }
 05057      return rr.Type;
 05058    }
 5059
 5060    /// <summary>
 5061    /// Resolve "memberName" in what currently is known as "receiverType". If "receiverType" is an unresolved
 5062    /// proxy type, try to solve enough type constraints and use heuristics to figure out which type contains
 5063    /// "memberName" and return that enclosing type as "tentativeReceiverType". However, try not to make
 5064    /// type-inference decisions about "receiverType"; instead, lay down the further constraints that need to
 5065    /// be satisfied in order for "tentativeReceiverType" to be where "memberName" is found.
 5066    /// Consequently, if "memberName" is found and returned as a "MemberDecl", it may still be the case that
 5067    /// "receiverType" is an unresolved proxy type and that, after solving more type constraints, "receiverType"
 5068    /// eventually gets set to a type more specific than "tentativeReceiverType".
 5069    /// </summary>
 89805070    public MemberDecl ResolveMember(IToken tok, Type receiverType, string memberName, out NonProxyType tentativeReceiver
 5071      Contract.Requires(tok != null);
 5072      Contract.Requires(receiverType != null);
 5073      Contract.Requires(memberName != null);
 5074      Contract.Ensures(Contract.Result<MemberDecl>() == null || Contract.ValueAtReturn(out tentativeReceiverType) != nul
 5075
 89805076      receiverType = PartiallyResolveTypeForMemberSelection(tok, receiverType, memberName);
 5077
 89805078      if (receiverType is TypeProxy) {
 05079        reporter.Error(MessageSource.Resolver, tok, "type of the receiver is not fully determined at this program point"
 05080        tentativeReceiverType = null;
 05081        return null;
 5082      }
 89805083      Contract.Assert(receiverType is NonProxyType);  // there are only two kinds of types: proxies and non-proxies
 5084
 2155205085      foreach (var valuet in valuetypeDecls) {
 628605086        if (valuet.IsThisType(receiverType)) {
 05087          if (valuet.Members.TryGetValue(memberName, out var member)) {
 05088            SelfType resultType = null;
 05089            if (member is SpecialFunction) {
 05090              resultType = ((SpecialFunction)member).ResultType as SelfType;
 05091            } else if (member is SpecialField) {
 05092              resultType = ((SpecialField)member).Type as SelfType;
 05093            }
 05094            if (resultType != null) {
 05095              SelfTypeSubstitution = new Dictionary<TypeParameter, Type>();
 05096              SelfTypeSubstitution.Add(resultType.TypeArg, receiverType);
 05097              resultType.ResolvedType = receiverType;
 05098            }
 05099            tentativeReceiverType = (NonProxyType)receiverType;
 05100            return member;
 5101          }
 05102          break;
 5103        }
 628605104      }
 5105
 89805106      var ctype = receiverType.NormalizeExpand() as UserDefinedType;
 89805107      var cd = ctype?.AsTopLevelTypeWithMembersBypassInternalSynonym;
 179605108      if (cd != null) {
 89805109        Contract.Assert(ctype.TypeArgs.Count == cd.TypeArgs.Count);  // follows from the fact that ctype was resolved
 89805110        if (!classMembers[cd].TryGetValue(memberName, out var member)) {
 05111          if (memberName == "_ctor") {
 05112            reporter.Error(MessageSource.Resolver, tok, "{0} {1} does not have an anonymous constructor", cd.WhatKind, c
 05113          } else {
 05114            reporter.Error(MessageSource.Resolver, tok, "member '{0}' does not exist in {2} '{1}'", memberName, cd.Name,
 05115          }
 89805116        } else if (!VisibleInScope(member)) {
 05117          reporter.Error(MessageSource.Resolver, tok, "member '{0}' has not been imported in this scope and cannot be ac
 89805118        } else {
 89805119          tentativeReceiverType = ctype;
 89805120          return member;
 5121        }
 05122        tentativeReceiverType = null;
 05123        return null;
 5124      }
 5125
 05126      reporter.Error(MessageSource.Resolver, tok, "type {0} does not have a member {1}", receiverType, memberName);
 05127      tentativeReceiverType = null;
 05128      return null;
 89805129    }
 5130
 5131    /// <summary>
 5132    /// Roughly speaking, tries to figure out the head of the type of "t", making as few inference decisions as possible
 5133    /// More precisely, returns a type that contains all the members of "t"; or if "memberName" is non-null, a type
 5134    /// that at least contains the member "memberName" of "t".  Typically, this type is the head type of "t",
 5135    /// but it may also be a type in a super- or subtype relation to "t".
 5136    /// In some cases, it is necessary to make some inference decisions in order to figure out the type to return.
 5137    /// </summary>
 628005138    public Type PartiallyResolveTypeForMemberSelection(IToken tok, Type t, string memberName = null, int strength = 0) {
 5139      Contract.Requires(tok != null);
 5140      Contract.Requires(t != null);
 5141      Contract.Ensures(Contract.Result<Type>() != null);
 5142      Contract.Ensures(!(Contract.Result<Type>() is TypeProxy) || ((TypeProxy)Contract.Result<Type>()).T == null);
 628005143      t = t.NormalizeExpand();
 793505144      if (!(t is TypeProxy)) {
 165505145        return t;  // we're good
 5146      }
 5147
 5148      // simplify constraints
 462505149      PrintTypeConstraintState(10);
 699705150      if (strength > 0) {
 237205151        var proxySpecializations = new HashSet<TypeProxy>();
 237205152        GetRelatedTypeProxies(t, proxySpecializations);
 237205153        var anyNewConstraintsAssignable = ConvertAssignableToSubtypeConstraints(proxySpecializations);
 237205154        var anyNewConstraintsEquatable = TightenUpEquatable(proxySpecializations);
 354305155        if ((strength > 1 && !anyNewConstraintsAssignable && !anyNewConstraintsEquatable) || strength == 10) {
 234205156          if (t is TypeProxy) {
 5157            // One more try
 117105158            var r = GetBaseTypeFromProxy((TypeProxy)t, new Dictionary<TypeProxy, Type>());
 117705159            if (r != null) {
 605160              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05161                Options.OutputWriter.WriteLine("  ----> found improvement through GetBaseTypeFromProxy: {0}", r);
 05162              }
 605163              return r;
 5164            }
 116505165          }
 5166
 116505167          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05168            Options.OutputWriter.WriteLine("  ----> found no improvement, giving up");
 05169          }
 116505170          return t;
 5171        }
 120105172      }
 345405173      PartiallySolveTypeConstraints(false);
 345405174      PrintTypeConstraintState(11);
 345405175      t = t.NormalizeExpandKeepConstraints();
 345405176      var proxy = t as TypeProxy;
 345405177      if (proxy == null) {
 05178        return t;  // simplification did the trick
 5179      }
 345405180      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05181        Options.OutputWriter.WriteLine("DEBUG: Member selection{3}:  {1} :> {0} :> {2}", t,
 05182          Util.Comma(proxy.SupertypesKeepConstraints, su => su.ToString()),
 05183          Util.Comma(proxy.SubtypesKeepConstraints, su => su.ToString()),
 05184          memberName == null ? "" : " (" + memberName + ")");
 05185      }
 5186
 5187      // Look for a join of head symbols among the proxy's subtypes
 345405188      Type joinType = null;
 432905189      if (JoinOfAllSubtypes(proxy, ref joinType, new HashSet<TypeProxy>()) && joinType != null) {
 87505190        DetermineRootLeaf(joinType, out _, out _, out var headIsRoot, out _);
 154905191        if (joinType.IsDatatype) {
 67405192          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05193            Options.OutputWriter.WriteLine("  ----> join is a datatype: {0}", joinType);
 05194          }
 67405195          ConstrainSubtypeRelation(t, joinType, tok, "Member selection requires a supertype of {0} (got something more l
 67405196          return joinType;
 34505197        } else if (headIsRoot) {
 5198          // we're good to go -- by picking "join" (whose type parameters have been replaced by fresh proxies), we're no
 14405199          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05200            Options.OutputWriter.WriteLine("  ----> improved to {0} through join", joinType);
 05201          }
 14405202          AssignProxyAndHandleItsConstraints(proxy, joinType, true);
 14405203          return proxy.NormalizeExpand();  // we return proxy.T instead of join, in case the assignment gets hijacked
 11405204        } else if (memberName == "_#apply" || memberName == "requires" || memberName == "reads") {
 5705205          var generalArrowType = joinType.AsArrowType;  // go all the way to the base type, to get to the general arrow 
 11405206          if (generalArrowType != null) {
 5207            // pick the supertype "generalArrowType" of "join"
 5705208            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05209              Options.OutputWriter.WriteLine("  ----> improved to {0} through join and function application", generalArr
 05210            }
 5705211            ConstrainSubtypeRelation(generalArrowType, t, tok, "Function application requires a subtype of {0} (got some
 5705212            return generalArrowType;
 5213          }
 05214        } else if (memberName != null) {
 5215          // If "join" has a member called "memberName" and no supertype of "join" does, then we'll pick this join
 05216          if (joinType.IsRefType) {
 05217            var joinExpanded = joinType.NormalizeExpand();  // go all the way to the base type, to get to the class
 05218            if (!joinExpanded.IsObjectQ) {
 05219              var cl = ((UserDefinedType)joinExpanded).ResolvedClass as ClassDecl;
 05220              if (cl != null) {
 5221                // TODO: the following could be improved by also supplying an upper bound of the search (computed as a j
 05222                var plausibleMembers = new HashSet<MemberDecl>();
 05223                FindAllMembers(cl, memberName, plausibleMembers);
 05224                if (plausibleMembers.Count == 1) {
 05225                  var mbr = plausibleMembers.First();
 05226                  if (mbr.EnclosingClass == cl) {
 05227                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05228                      Options.OutputWriter.WriteLine("  ----> improved to {0} through member-selection join", joinType);
 05229                    }
 05230                    var joinRoot = joinType.NormalizeExpand();  // blow passed any constraints
 05231                    ConstrainSubtypeRelation(joinRoot, t, tok, "Member selection requires a subtype of {0} (got somethin
 05232                    return joinType;
 05233                  } else {
 5234                    // pick the supertype "mbr.EnclosingClass" of "cl"
 05235                    Contract.Assert(mbr.EnclosingClass is TraitDecl);  // a proper supertype of a ClassDecl must be a Tr
 05236                    var typeMapping = cl.ParentFormalTypeParametersToActuals;
 05237                    TopLevelDecl td = mbr.EnclosingClass;
 05238                    foreach (var tt in cl.TraitAncestors()) {
 5239                      // If there is a match, the list of Type actuals is unique
 5240                      // (a class cannot inherit both Trait<T1> and Trait<T2> with T1 != T2).
 05241                      if (tt == (TraitDecl)mbr.EnclosingClass) {
 05242                        td = tt;
 05243                      }
 05244                    }
 05245                    List<Type> proxyTypeArgs = td.TypeArgs.ConvertAll(t0 => typeMapping.ContainsKey(t0) ? typeMapping[t0
 05246                    var joinMapping = TypeParameter.SubstitutionMap(cl.TypeArgs, joinType.TypeArgs);
 05247                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.Subst(joinMapping));
 05248                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.AsTypeParameter == null ? t0 : (Type)new InferredT
 05249                    var pickItFromHere = new UserDefinedType(tok, mbr.EnclosingClass.Name, mbr.EnclosingClass, proxyType
 05250                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05251                      Options.OutputWriter.WriteLine("  ----> improved to {0} through join and member lookup", pickItFro
 05252                    }
 05253                    ConstrainSubtypeRelation(pickItFromHere, t, tok, "Member selection requires a subtype of {0} (got so
 05254                    return pickItFromHere;
 5255                  }
 5256                }
 05257              }
 05258            }
 05259          }
 05260        }
 05261        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05262          Options.OutputWriter.WriteLine("  ----> found no improvement, because join does not determine type enough");
 05263        }
 05264      }
 5265
 5266      // Compute the meet of the proxy's supertypes
 257905267      Type meet = null;
 273905268      if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null) {
 5269        // If the meet does have the member, then this looks promising. It could be that the
 5270        // type would get further constrained later to pick some subtype (in particular, a
 5271        // subclass that overrides the member) of this meet. But this is the best we can do
 5272        // now.
 20205273        if (meet is TypeProxy) {
 4205274          if (proxy == meet.Normalize()) {
 5275            // can this really ever happen?
 05276            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05277              Options.OutputWriter.WriteLine("  ----> found no improvement (other than the proxy itself)");
 05278            }
 05279            return t;
 4205280          } else {
 4205281            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05282              Options.OutputWriter.WriteLine("  ----> (merging, then trying to improve further) assigning proxy {0}.T :=
 05283            }
 4205284            Contract.Assert(proxy != meet);
 4205285            proxy.T = meet;
 4205286            Contract.Assert(t.NormalizeExpand() == meet);
 4205287            return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 5288          }
 5289        }
 13105290        if (!(meet is ArtificialType)) {
 1305291          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05292            Options.OutputWriter.WriteLine("  ----> improved to {0} through meet", meet);
 05293          }
 1305294          if (memberName != null) {
 05295            AssignProxyAndHandleItsConstraints(proxy, meet, true);
 05296            return proxy.NormalizeExpand(); // we return proxy.T instead of meet, in case the assignment gets hijacked
 1305297          } else {
 1305298            return meet;
 5299          }
 5300        }
 10505301      }
 5302
 5303      // as a last resort, act on any artificial type nearby the proxy
 252405304      var artificialSuper = proxy.InClusterOfArtificial(AllXConstraints);
 271805305      if (artificialSuper != null) {
 19405306        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05307          Options.OutputWriter.WriteLine("  ----> use artificial supertype: {0}", artificialSuper);
 05308        }
 19405309        return artificialSuper;
 5310      }
 5311
 5312      // we weren't able to do it
 233005313      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05314        Options.OutputWriter.WriteLine("  ----> found no improvement using simple things, trying harder once more");
 05315      }
 233005316      return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 628005317    }
 5318
 120505319    private Type/*?*/ GetBaseTypeFromProxy(TypeProxy proxy, Dictionary<TypeProxy, Type/*?*/> determinedProxies) {
 5320      Contract.Requires(proxy != null);
 5321      Contract.Requires(determinedProxies != null);
 121905322      if (determinedProxies.TryGetValue(proxy, out var t)) {
 5323        // "t" may be null (meaning search for "proxy" is underway or was unsuccessful) or non-null (search for
 5324        // "proxy" has completed successfully), but we return it in either case
 1405325        return t;
 5326      }
 119105327      determinedProxies.Add(proxy, null);  // record that search for "proxy" is underway
 5328      // First, go through subtype constraints, treating each as if it were an equality
 183798705329      foreach (var c in AllTypeConstraints) {
 61147905330        t = GetBaseTypeFromProxy_Eq(proxy, c.Super, c.Sub, determinedProxies);
 61150205331        if (t != null) {
 2305332          determinedProxies[proxy] = t;
 2305333          return t;
 5334        }
 61145605335      }
 5336      // Next, check XConstraints that can be seen as equality constraints
 297169905337      foreach (var xc in AllXConstraints) {
 98939905338        switch (xc.ConstraintName) {
 5339          case "Assignable":
 5340          case "Equatable":
 5341          case "EquatableArg":
 93683605342            t = GetBaseTypeFromProxy_Eq(proxy, xc.Types[0], xc.Types[1], determinedProxies);
 93683805343            if (t != null) {
 205344              determinedProxies[proxy] = t;
 205345              return t;
 5346            }
 93683405347            break;
 5348          case "InSet":
 5349            // etc. TODO
 05350            break;
 5351          default:
 5256305352            break;
 5353        }
 98939705354      }
 116605355      return null;
 120505356    }
 5357    /// <summary>
 5358    /// Tries to find a non-proxy type corresponding to "proxy", under the assumption that "t" equals "u" and
 5359    /// "determinedProxies" assumptions.  In the process, may add to "determinedProxies".
 5360    /// </summary>
 154831505361    private Type/*?*/ GetBaseTypeFromProxy_Eq(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> determin
 5362      Contract.Requires(proxy != null);
 5363      Contract.Requires(determinedProxies != null);
 5364      Contract.Requires(t != null);
 5365      Contract.Requires(u != null);
 154831505366      t = t.NormalizeExpand();
 154831505367      u = u.NormalizeExpand();
 154831505368      return GetBaseTypeFromProxy_EqAux(proxy, t, u, determinedProxies) ?? GetBaseTypeFromProxy_EqAux(proxy, u, t, deter
 154831505369    }
 309661705370    private Type/*?*/ GetBaseTypeFromProxy_EqAux(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> deter
 5371      Contract.Requires(proxy != null);
 5372      Contract.Requires(determinedProxies != null);
 5373      Contract.Requires(t != null && (!(t is TypeProxy) || ((TypeProxy)t).T == null));
 5374      Contract.Requires(u != null && (!(u is TypeProxy) || ((TypeProxy)u).T == null));
 309665705375      if (t == proxy) {
 7405376        if (u is TypeProxy) {
 3405377          return GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 605378        } else {
 605379          return u;
 5380        }
 309657705381      } else if (t.ContainsProxy(proxy)) {
 05382        if (u is TypeProxy) {
 05383          u = GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 05384          if (u == null) {
 05385            return null;
 5386          }
 05387        }
 05388        if (Type.SameHead(t, u)) {
 05389          Contract.Assert(t.TypeArgs.Count == u.TypeArgs.Count);
 05390          for (int i = 0; i < t.TypeArgs.Count; i++) {
 05391            var r = GetBaseTypeFromProxy_Eq(proxy, t.TypeArgs[i], u.TypeArgs[i], determinedProxies);
 05392            if (r != null) {
 05393              return r;
 5394            }
 05395          }
 05396        }
 05397      }
 309657705398      return null;
 309661705399    }
 5400
 246205401    private void GetRelatedTypeProxies(Type t, ISet<TypeProxy> proxies) {
 5402      Contract.Requires(t != null);
 5403      Contract.Requires(proxies != null);
 246205404      var proxy = t.Normalize() as TypeProxy;
 249005405      if (proxy == null || proxies.Contains(proxy)) {
 2805406        return;
 5407      }
 243405408      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05409        Options.OutputWriter.WriteLine("DEBUG: GetRelatedTypeProxies: finding {0} interesting", proxy);
 05410      }
 243405411      proxies.Add(proxy);
 5412      // close over interesting constraints
 377737505413      foreach (var c in AllTypeConstraints) {
 125669105414        var super = c.Super.Normalize();
 158608205415        if (super.TypeArgs.Exists(ta => ta.Normalize() == proxy)) {
 1005416          GetRelatedTypeProxies(c.Sub, proxies);
 1005417        }
 125669105418      }
 617828405419      foreach (var xc in AllXConstraints) {
 205699405420        var xc0 = xc.Types[0].Normalize();
 208139205421        if (xc.ConstraintName == "Assignable" && (xc0 == proxy || xc0.TypeArgs.Exists(ta => ta.Normalize() == proxy))) {
 8005422          GetRelatedTypeProxies(xc.Types[1], proxies);
 205699405423        } else if (xc.ConstraintName == "Innable" && xc.Types[1].Normalize() == proxy) {
 05424          GetRelatedTypeProxies(xc.Types[0], proxies);
 205691405425        } else if ((xc.ConstraintName == "ModifiesFrame" || xc.ConstraintName == "ReadsFrame") && xc.Types[1].Normalize(
 05426          GetRelatedTypeProxies(xc.Types[0], proxies);
 05427        }
 205699405428      }
 246205429    }
 5430
 5431    /// <summary>
 5432    /// Attempts to compute the join of "join", "t", and all of "t"'s known subtype( constraint)s.  The join
 5433    /// ignores type parameters.  It is assumed that "join" on entry already includes the join of all proxies
 5434    /// in "visited". The empty join is represented by "null".
 5435    /// The return is "true" if the join exists.
 5436    /// </summary>
 577905437    bool JoinOfAllSubtypes(Type t, ref Type joinType, ISet<TypeProxy> visited) {
 5438      Contract.Requires(t != null);
 5439      Contract.Requires(visited != null);
 5440
 577905441      t = t.NormalizeExpandKeepConstraints();
 5442
 577905443      var proxy = t as TypeProxy;
 1063805444      if (proxy != null) {
 524405445        if (visited.Contains(proxy)) {
 38505446          return true;
 5447        }
 447405448        visited.Add(proxy);
 5449
 1502105450        foreach (var c in proxy.SubtypeConstraints) {
 53305451          var s = c.Sub.NormalizeExpandKeepConstraints();
 53305452          if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05453            return false;
 5454          }
 53305455        }
 873705456        if (joinType == null) {
 5457          // also consider "Assignable" constraints
 985889405458          foreach (var c in AllXConstraints) {
 328379205459            if (c.ConstraintName == "Assignable" && c.Types[0].Normalize() == proxy) {
 175705460              var s = c.Types[1].NormalizeExpandKeepConstraints();
 175705461              if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05462                return false;
 5463              }
 175705464            }
 328203505465          }
 426305466        }
 447405467        return true;
 5468      }
 5469
 183005470      if (joinType == null) {
 5471        // stick with what we've got
 91005472        joinType = t;
 91005473        return true;
 2005474      } else if (Type.IsHeadSupertypeOf(joinType, t)) {
 5475        // stick with what we've got
 1005476        return true;
 05477      } else if (Type.IsHeadSupertypeOf(t, joinType)) {
 05478        joinType = Type.HeadWithProxyArgs(t);
 05479        return true;
 05480      } else {
 05481        joinType = Type.Join(joinType, Type.HeadWithProxyArgs(t), builtIns);  // the only way this can succeed is if we 
 05482        Contract.Assert(joinType == null ||
 05483                        joinType.IsObjectQ || joinType.IsObject ||
 05484                        (joinType is UserDefinedType udt && (udt.ResolvedClass is TraitDecl || (udt.ResolvedClass is Non
 05485        return joinType != null;
 5486      }
 577905487    }
 5488
 5489    /// <summary>
 5490    /// Attempts to compute the meet of "meet", all of "t"'s known supertype( constraint)s, and, if "includeT"
 5491    /// and "t" has no supertype( constraint)s, "t".
 5492    /// The meet ignores type parameters. (Really?? --KRML)
 5493    /// It is assumed that "meet" on entry already includes the meet of all proxies
 5494    /// in "visited". The empty meet is represented by "null".
 5495    /// The return is "true" if the meet exists.
 5496    /// </summary>
 293905497    bool MeetOfAllSupertypes(Type t, ref Type meet, ISet<TypeProxy> visited, bool includeT) {
 5498      Contract.Requires(t != null);
 5499      Contract.Requires(visited != null);
 5500
 293905501      t = t.NormalizeExpandKeepConstraints();
 293905502      var proxy = t as TypeProxy;
 573805503      if (proxy != null) {
 286505504        if (visited.Contains(proxy)) {
 6605505          return true;
 5506        }
 273305507        visited.Add(proxy);
 5508
 273305509        var delegatedToOthers = false;
 901805510        foreach (var c in proxy.SupertypeConstraints) {
 28305511          var s = c.Super.NormalizeExpandKeepConstraints();
 28305512          delegatedToOthers = true;
 31305513          if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 3005514            return false;
 5515          }
 25305516        }
 523705517        if (!delegatedToOthers) {
 5518          // also consider "Assignable" constraints
 638567105519          foreach (var c in AllXConstraints) {
 212610505520            if (c.ConstraintName == "Assignable" && c.Types[1].Normalize() == proxy) {
 7705521              var s = c.Types[0].NormalizeExpandKeepConstraints();
 7705522              delegatedToOthers = true;
 9205523              if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 1505524                return false;
 5525              }
 6205526            }
 212601305527          }
 251905528        }
 290505529        if (delegatedToOthers) {
 21705530          return true;
 484505531        } else if (!includeT) {
 237405532          return true;
 17105533        } else if (meet == null || meet.Normalize() == proxy) {
 7405534          meet = proxy;
 7405535          return true;
 2305536        } else {
 2305537          return false;
 5538        }
 5539      }
 5540
 26005541      if (meet == null) {
 12005542        meet = Type.HeadWithProxyArgs(t);
 12005543        return true;
 2905544      } else if (Type.IsHeadSupertypeOf(t, meet)) {
 5545        // stick with what we've got
 905546        return true;
 1105547      } else if (Type.IsHeadSupertypeOf(meet, t)) {
 05548        meet = Type.HeadWithProxyArgs(t);
 05549        return true;
 1105550      } else {
 1105551        meet = Type.Meet(meet, Type.HeadWithProxyArgs(t), builtIns);
 1105552        return meet != null;
 5553      }
 293905554    }
 5555
 5556    /// <summary>
 5557    /// Check that the type uses formal type parameters in a way that is agreeable with their variance specifications.
 5558    /// "context == Co" says that "type" is allowed to vary in the positive direction.
 5559    /// "context == Contra" says that "type" is allowed to vary in the negative direction.
 5560    /// "context == Non" says that "type" must not vary at all.
 5561    /// * "lax" says that the context is not strict -- type parameters declared to be strict must not be used in a lax c
 5562    /// </summary>
 13355563    public void CheckVariance(Type type, ICallable enclosingTypeDefinition, TypeParameter.TPVariance context, bool lax) 
 5564      Contract.Requires(type != null);
 5565      Contract.Requires(enclosingTypeDefinition != null);
 5566
 13355567      type = type.Normalize();  // we keep constraints, since subset types have their own type-parameter variance specif
 13355568      if (type is BasicType) {
 5569        // fine
 13355570      } else if (type is MapType) {
 05571        var t = (MapType)type;
 5572        // If its an infinite map, the domain's context is lax
 05573        CheckVariance(t.Domain, enclosingTypeDefinition, context, lax || !t.Finite);
 05574        CheckVariance(t.Range, enclosingTypeDefinition, context, lax);
 13355575      } else if (type is SetType) {
 05576        var t = (SetType)type;
 5577        // If its an infinite set, the argument's context is lax
 05578        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax || !t.Finite);
 13355579      } else if (type is CollectionType) {
 05580        var t = (CollectionType)type;
 05581        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax);
 26705582      } else if (type is UserDefinedType) {
 13355583        var t = (UserDefinedType)type;
 17805584        if (t.ResolvedClass is TypeParameter tp) {
 4455585          if (tp.Variance != TypeParameter.TPVariance.Non && tp.Variance != context) {
 05586            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 4455587          } else if (tp.StrictVariance && lax) {
 5588            string hint;
 05589            if (tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.NonVariant_Strict) {
 05590              hint = string.Format(" (perhaps try declaring '{0}' as '-{0}' or '!{0}')", tp.Name);
 05591            } else {
 05592              Contract.Assert(tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.Covariant_Strict);
 05593              hint = string.Format(" (perhaps try changing the declaration from '+{0}' to '*{0}')", tp.Name);
 05594            }
 05595            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 05596          }
 13355597        } else {
 8905598          var resolvedClass = t.ResolvedClass;
 8905599          Contract.Assert(resolvedClass != null);  // follows from that the given type was successfully resolved
 8905600          Contract.Assert(resolvedClass.TypeArgs.Count == t.TypeArgs.Count);
 8905601          if (lax) {
 5602            // we have to be careful about uses of the type being defined
 05603            var cg = enclosingTypeDefinition.EnclosingModule.CallGraph;
 05604            var t0 = resolvedClass as ICallable;
 05605            if (t0 != null && cg.GetSCCRepresentative(t0) == cg.GetSCCRepresentative(enclosingTypeDefinition)) {
 05606              reporter.Error(MessageSource.Resolver, t.tok, "using the type being defined ('{0}') here would cause a log
 05607            }
 05608          }
 31155609          for (int i = 0; i < t.TypeArgs.Count; i++) {
 4455610            Type p = t.TypeArgs[i];
 4455611            var tpFormal = resolvedClass.TypeArgs[i];
 4455612            CheckVariance(p, enclosingTypeDefinition,
 4455613              context == TypeParameter.TPVariance.Non ? context :
 4455614              context == TypeParameter.TPVariance.Co ? tpFormal.Variance :
 4455615              TypeParameter.Negate(tpFormal.Variance),
 4455616              lax || !tpFormal.StrictVariance);
 4455617          }
 8905618        }
 13355619      } else {
 05620        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 5621      }
 13355622    }
 5623
 5624    /// <summary>
 5625    /// See ConstrainToIntegerType description for the overload above.
 5626    /// </summary>
 199205627    void ConstrainToIntegerType(IToken tok, Type type, bool allowBitVector, TypeConstraint.ErrorMsg errorMsg) {
 5628      Contract.Requires(tok != null);
 5629      Contract.Requires(type != null);
 5630      Contract.Requires(errorMsg != null);
 5631      // We do two constraints: the first can aid in determining types, but allows bit-vectors; the second excludes bit-
 5632      // However, we reuse the error message, so that only one error gets reported.
 199205633      ConstrainSubtypeRelation(new IntVarietiesSupertype(), type, errorMsg);
 202605634      if (!allowBitVector) {
 3405635        AddXConstraint(tok, "IntegerType", type, errorMsg);
 3405636      }
 199205637    }
 5638
 5639    /// <summary>
 5640    /// Attempts to rewrite a datatype update into more primitive operations, after doing the appropriate resolution che
 5641    /// Upon success, returns that rewritten expression and sets "legalSourceConstructors".
 5642    /// Upon some resolution error, return null.
 5643    ///
 5644    /// Actually, the method returns two expressions (or returns "(null, null)"). The first expression is the desugaring
 5645    /// used when the DatatypeUpdateExpr is used in a ghost context. The second is to be used for a compiled context. In
 5646    /// case, "legalSourceConstructors" contains both ghost and compiled constructors.
 5647    ///
 5648    /// The reason for computing both desugarings here is that it's too early to tell if the DatatypeUpdateExpr is being
 5649    /// a ghost or compiled context. This is a consequence of doing the deguaring so early. But it's also convenient to 
 5650    /// desugaring during resolution, because then the desugaring can be constructed as a non-resolved expression on whi
 5651    /// is called--this is easier than constructing an already-resolved expression.
 5652    /// </summary>
 5653    (Expression, Expression) ResolveDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<Tuple<IToken, stri
 05654      ResolutionContext resolutionContext, out List<MemberDecl> members, out List<DatatypeCtor> legalSourceConstructors)
 5655      Contract.Requires(tok != null);
 5656      Contract.Requires(root != null);
 5657      Contract.Requires(dt != null);
 5658      Contract.Requires(memberUpdates != null);
 5659      Contract.Requires(resolutionContext != null);
 5660
 05661      legalSourceConstructors = null;
 05662      members = new List<MemberDecl>();
 5663
 5664      // First, compute the list of candidate result constructors, that is, the constructors
 5665      // that have all of the mentioned destructors. Issue errors for duplicated names and for
 5666      // names that are not destructors in the datatype.
 05667      var candidateResultCtors = dt.Ctors;  // list of constructors that have all the so-far-mentioned destructors
 05668      var memberNames = new HashSet<string>();
 05669      var rhsBindings = new Dictionary<string, Tuple<BoundVar/*let variable*/, IdentifierExpr/*id expr for let variable*
 05670      var subst = TypeParameter.SubstitutionMap(dt.TypeArgs, root.Type.NormalizeExpand().TypeArgs);
 05671      foreach (var entry in memberUpdates) {
 05672        var destructor_str = entry.Item2;
 05673        if (memberNames.Contains(destructor_str)) {
 05674          reporter.Error(MessageSource.Resolver, entry.Item1, "duplicate update member '{0}'", destructor_str);
 05675        } else {
 05676          memberNames.Add(destructor_str);
 05677          if (!classMembers[dt].TryGetValue(destructor_str, out var member)) {
 05678            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' does not exist in datatype '{1}'", destruc
 05679          } else if (!(member is DatatypeDestructor)) {
 05680            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' is not a destructor in datatype '{1}'", de
 05681          } else {
 05682            members.Add(member);
 05683            var destructor = (DatatypeDestructor)member;
 05684            var intersection = new List<DatatypeCtor>(candidateResultCtors.Intersect(destructor.EnclosingCtors));
 05685            if (intersection.Count == 0) {
 05686              reporter.Error(MessageSource.Resolver, entry.Item1,
 05687                "updated datatype members must belong to the same constructor (unlike the previously mentioned destructo
 05688                destructor_str, DatatypeDestructor.PrintableCtorNameList(candidateResultCtors, "or"));
 05689            } else {
 05690              candidateResultCtors = intersection;
 05691              if (destructor.IsGhost) {
 05692                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(null, null, entry.Item3)
 05693              } else {
 05694                var xName = FreshTempVarName(string.Format("dt_update#{0}#", destructor_str), resolutionContext.CodeCont
 05695                var xVar = new BoundVar(new AutoGeneratedToken(tok), xName, destructor.Type.Subst(subst));
 05696                var x = new IdentifierExpr(new AutoGeneratedToken(tok), xVar);
 05697                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(xVar, x, entry.Item3));
 05698              }
 05699            }
 05700          }
 05701        }
 05702      }
 05703      if (candidateResultCtors.Count == 0) {
 05704        return (null, null);
 5705      }
 5706
 5707      // Check that every candidate result constructor has given a name to all of its parameters.
 05708      var hasError = false;
 05709      foreach (var ctor in candidateResultCtors) {
 05710        if (ctor.Formals.Exists(f => !f.HasName)) {
 05711          reporter.Error(MessageSource.Resolver, tok,
 05712            "candidate result constructor '{0}' has an anonymous parameter (to use in datatype update expression, name a
 05713            ctor.Name);
 05714          hasError = true;
 05715        }
 05716      }
 05717      if (hasError) {
 05718        return (null, null);
 5719      }
 5720
 5721      // The legal source constructors are the candidate result constructors. (Yep, two names for the same thing.)
 05722      legalSourceConstructors = candidateResultCtors;
 05723      Contract.Assert(1 <= legalSourceConstructors.Count);
 5724
 05725      var desugaringForGhostContext = DesugarDatatypeUpdate(tok, root, dt, candidateResultCtors, rhsBindings, resolution
 05726      var nonGhostConstructors = candidateResultCtors.Where(ctor => !ctor.IsGhost).ToList();
 05727      if (nonGhostConstructors.Count == candidateResultCtors.Count) {
 05728        return (desugaringForGhostContext, desugaringForGhostContext);
 5729      }
 05730      var desugaringForCompiledContext = DesugarDatatypeUpdate(tok, root, dt, nonGhostConstructors, rhsBindings, resolut
 05731      return (desugaringForGhostContext, desugaringForCompiledContext);
 05732    }
 5733
 5734    /// <summary>
 5735    // Rewrite the datatype update root.(x := X, y := Y, ...) to:
 5736    ///     var d := root;
 5737    ///     var x := X;  // EXCEPT: don't do this for ghost fields
 5738    ///     var y := Y;
 5739    ///     ..
 5740    ///     if d.CandidateResultConstructor0 then
 5741    ///       CandidateResultConstructor0(x, y, ..., d.f0, d.f1, ...)  // for a ghost field x, use the expression X dire
 5742    ///     else if d.CandidateResultConstructor1 then
 5743    ///       CandidateResultConstructor0(x, y, ..., d.g0, d.g1, ...)
 5744    ///     ...
 5745    ///     else
 5746    ///       CandidateResultConstructorN(x, y, ..., d.k0, d.k1, ...)
 5747    /// </summary>
 5748    private Expression DesugarDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<DatatypeCtor> candidateR
 05749      Dictionary<string, Tuple<BoundVar, IdentifierExpr, Expression>> rhsBindings, ResolutionContext resolutionContext) 
 5750
 05751      if (candidateResultCtors.Count == 0) {
 05752        return root;
 5753      }
 05754      Expression rewrite = null;
 5755      // Create a unique name for d', the variable we introduce in the let expression
 05756      var dName = FreshTempVarName("dt_update_tmp#", resolutionContext.CodeContext);
 05757      var dVar = new BoundVar(new AutoGeneratedToken(tok), dName, root.Type);
 05758      var d = new IdentifierExpr(new AutoGeneratedToken(tok), dVar);
 05759      Expression body = null;
 05760      candidateResultCtors.Reverse();
 05761      foreach (var crc in candidateResultCtors) {
 5762        // Build the arguments to the datatype constructor, using the updated value in the appropriate slot
 05763        var ctorArguments = new List<Expression>();
 05764        var actualBindings = new List<ActualBinding>();
 05765        foreach (var f in crc.Formals) {
 5766          Expression ctorArg;
 05767          if (rhsBindings.TryGetValue(f.Name, out var info)) {
 05768            ctorArg = info.Item2 ?? info.Item3;
 05769          } else {
 05770            ctorArg = new ExprDotName(tok, d, f.Name, null);
 05771          }
 05772          ctorArguments.Add(ctorArg);
 05773          var bindingName = new Token(tok.line, tok.col) {
 05774            Uri = tok.Uri,
 05775            val = f.Name
 05776          };
 05777          actualBindings.Add(new ActualBinding(bindingName, ctorArg));
 05778        }
 05779        var ctor_call = new DatatypeValue(tok, crc.EnclosingDatatype.Name, crc.Name, actualBindings);
 5780        // in the following line, resolve to root.Type, so that type parameters get filled in appropriately
 05781        ResolveDatatypeValue(resolutionContext, ctor_call, dt, root.Type.NormalizeExpand());
 5782
 05783        if (body == null) {
 05784          body = ctor_call;
 05785        } else {
 5786          // body = if d.crc? then ctor_call else body
 05787          var guard = new ExprDotName(tok, d, crc.QueryField.Name, null);
 05788          body = new ITEExpr(tok, false, guard, ctor_call, body);
 05789        }
 05790      }
 05791      Contract.Assert(body != null); // because there was at least one element in candidateResultCtors
 5792
 5793      // Wrap the let's around body
 05794      rewrite = body;
 05795      foreach (var entry in rhsBindings) {
 05796        if (entry.Value.Item1 != null) {
 05797          var lhs = new CasePattern<BoundVar>(tok, entry.Value.Item1);
 05798          rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { entry.Value.Ite
 05799        }
 05800      }
 05801      var dVarPat = new CasePattern<BoundVar>(tok, dVar);
 05802      rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { dVarPat }, new List<Expression>() { root }, rewrite
 05803      Contract.Assert(rewrite != null);
 05804      ResolveExpression(rewrite, resolutionContext);
 05805      return rewrite;
 05806    }
 5807
 5808    public Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args,
 7770955809      ResolutionContext resolutionContext, bool allowMethodCall, bool complain = true) {
 7770955810      return ResolveNameSegment(expr, isLastNameSegment, args, resolutionContext, allowMethodCall, complain, out _);
 7770955811    }
 5812
 5813    /// <summary>
 5814    /// Look up expr.Name in the following order:
 5815    ///  0. Local variable, parameter, or bound variable.
 5816    ///     (Language design note:  If this clashes with something of interest, one can always rename the local variable
 5817    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 5818    ///  2. If isLastNameSegment:
 5819    ///     Unambiguous constructor name of a datatype in the enclosing module (if two constructors have the same name, 
 5820    ///     (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority, on
 5821    ///  3. Member of the enclosing module (type name or the name of a module)
 5822    ///  4. Static function or method in the enclosing module or its imports
 5823    ///  5. If !isLastNameSegment:
 5824    ///     Unambiguous constructor name of a datatype in the enclosing module
 5825    ///
 5826    /// </summary>
 5827    /// <param name="expr"></param>
 5828    /// <param name="isLastNameSegment">Indicates that the NameSegment is not directly enclosed in another NameSegment o
 5829    /// <param name="args">If the NameSegment is enclosed in an ApplySuffix, then these are the arguments.  The method r
 5830    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 5831    /// that incorporates these arguments.</param>
 5832    /// <param name="resolutionContext"></param>
 5833    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 5834    /// a MemberSelectExpr whose .Member is a Method.</param>
 5835    /// <param name="shadowedModule">If the name being resolved shadows an imported module, then that module is reported
 5836    /// through this parameter.  This happens when module <c>Option</c> in <c>import opened Option</c> also contains a
 5837    /// <c>datatype Option</c>, in which case <c>Option</c> refers to the datatype, not the module
 5838    /// (https://github.com/dafny-lang/dafny/issues/1996).</param>
 7830455839    Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext 
 5840      Contract.Requires(expr != null);
 5841      Contract.Requires(!expr.WasResolved());
 5842      Contract.Requires(resolutionContext != null);
 5843      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 5844
 7830455845      shadowedModule = null;
 5846
 7830455847      if (expr.OptTypeArguments != null) {
 05848        foreach (var ty in expr.OptTypeArguments) {
 05849          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 05850        }
 05851      }
 5852
 7830455853      Expression r = null;  // the resolved expression, if successful
 7830455854      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 5855
 5856      // For 0:
 5857      IVariable v;
 5858      // For 1:
 5859      // For 1 and 4:
 7830455860      MemberDecl member = null;
 5861      // For 2 and 5:
 5862      // For 3:
 5863
 7830455864      var name = resolutionContext.InReveal ? "reveal_" + expr.Name : expr.Name;
 7830455865      v = scope.Find(name);
 15442705866      if (v != null) {
 5867        // ----- 0. local variable, parameter, or bound variable
 7612255868        if (expr.OptTypeArguments != null) {
 05869          if (complain) {
 05870            reporter.Error(MessageSource.Resolver, expr.tok, "variable '{0}' does not take any type parameters", name);
 05871          } else {
 05872            expr.ResolvedExpression = null;
 05873            return null;
 5874          }
 05875        }
 7612255876        r = new IdentifierExpr(expr.tok, v);
 8048655877      } else if (currentClass is TopLevelDeclWithMembers cl && classMembers.TryGetValue(cl, out var members) && members.
 5878        // ----- 1. member of the enclosing class
 5879        Expression receiver;
 436405880        if (member.IsStatic) {
 218205881          receiver = new StaticReceiverExpr(expr.tok, UserDefinedType.FromTopLevelDecl(expr.tok, currentClass, currentCl
 218205882        } else {
 05883          if (!scope.AllowInstance) {
 05884            if (complain) {
 05885              reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context"); //TODO: R
 05886            } else {
 05887              expr.ResolvedExpression = null;
 05888              return null;
 5889            }
 5890            // nevertheless, set "receiver" to a value so we can continue resolution
 05891          }
 05892          receiver = new ImplicitThisExpr(expr.tok);
 05893          receiver.Type = GetThisType(expr.tok, currentClass);  // resolve here
 05894        }
 218205895        r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allowMe
 218205896      } else if (isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out var pair)) {
 5897        // ----- 2. datatype constructor
 05898        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05899          return null;
 5900        }
 05901      } else if (moduleInfo.TopLevels.TryGetValue(name, out var decl)) {
 5902        // ----- 3. Member of the enclosing module
 5903
 5904        // Record which imported module, if any, was shadowed by `name` in the current module.
 05905        shadowedModule = moduleInfo.ShadowedImportedModules.GetValueOrDefault(name);
 5906
 05907        if (decl is AmbiguousTopLevelDecl) {
 05908          var ad = (AmbiguousTopLevelDecl)decl;
 05909          if (complain) {
 05910            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 05911          } else {
 05912            expr.ResolvedExpression = null;
 05913            return null;
 5914          }
 05915        } else {
 5916          // We have found a module name or a type name, neither of which is an expression. However, the NameSegment we'
 5917          // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of t
 5918          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 5919          // or verifier, just to have a placeholder where we can recorded what we have found.
 05920          if (!isLastNameSegment) {
 05921            if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 5922              // A possibly-null type C? was mentioned. But it does not have any further members. The program should hav
 5923              // the name of the class, C. Report an error and continue.
 05924              if (complain) {
 05925                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 05926              } else {
 05927                expr.ResolvedExpression = null;
 05928                return null;
 5929              }
 05930            }
 05931          }
 05932          r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 05933        }
 5934
 05935      } else if (moduleInfo.StaticMembers.TryGetValue(name, out member)) {
 5936        // ----- 4. static member of the enclosing module
 05937        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 05938        if (member is AmbiguousMemberDecl) {
 05939          var ambiguousMember = (AmbiguousMemberDecl)member;
 05940          if (complain) {
 05941            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 05942          } else {
 05943            expr.ResolvedExpression = null;
 05944            return null;
 5945          }
 05946        } else {
 05947          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass, true);
 05948          r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allow
 05949        }
 5950
 05951      } else if (!isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out pair)) {
 5952        // ----- 5. datatype constructor
 05953        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05954          return null;
 5955        }
 5956
 05957      } else {
 5958        // ----- None of the above
 05959        if (complain) {
 05960          if (resolutionContext.InReveal) {
 05961            reporter.Error(MessageSource.Resolver, expr.tok, "cannot reveal '{0}' because no constant, assert label, or 
 05962          } else {
 05963            reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 05964          }
 05965        } else {
 05966          expr.ResolvedExpression = null;
 05967          return null;
 5968        }
 05969      }
 5970
 7830455971      if (r == null) {
 5972        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 05973        expr.Type = new InferredTypeProxy();
 7830455974      } else {
 7830455975        expr.ResolvedExpression = r;
 7830455976        var rt = r.Type;
 7830455977        var nt = rt.UseInternalSynonym();
 7830455978        expr.Type = nt;
 7830455979      }
 7830455980      return rWithArgs;
 7830455981    }
 5982
 05983    private bool ResolveDatatypeConstructor(NameSegment expr, List<ActualBinding>/*?*/ args, ResolutionContext resolutio
 5984      Contract.Requires(expr != null);
 5985      Contract.Requires(resolutionContext != null);
 5986
 05987      if (pair.Item2) {
 5988        // there is more than one constructor with this name
 05989        if (complain) {
 05990          reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor, but does not 
 05991            pair.Item1.EnclosingDatatype.Name);
 05992        } else {
 05993          expr.ResolvedExpression = null;
 05994          return true;
 5995        }
 05996      } else {
 05997        if (expr.OptTypeArguments != null) {
 05998          if (complain) {
 05999            reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters ('{
 06000          } else {
 06001            expr.ResolvedExpression = null;
 06002            return true;
 6003          }
 06004        }
 06005        var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>())
 06006        bool ok = ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null, complain);
 06007        if (!ok) {
 06008          expr.ResolvedExpression = null;
 06009          return true;
 6010        }
 06011        if (args == null) {
 06012          r = rr;
 06013        } else {
 06014          r = rr; // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been proper to 
 06015          rWithArgs = rr;
 06016        }
 06017      }
 06018      return false;
 06019    }
 6020
 6021    /// <summary>
 6022    /// Look up expr.Name in the following order:
 6023    ///  0. Type parameter
 6024    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 6025    ///  2. Member of the enclosing module (type name or the name of a module)
 6026    ///  3. Static function or method in the enclosing module or its imports
 6027    ///
 6028    /// Note: 1 and 3 are not used now, but they will be of interest when async task types are supported.
 6029    /// </summary>
 1198806030    void ResolveNameSegment_Type(NameSegment expr, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 6031      Contract.Requires(expr != null);
 6032      Contract.Requires(!expr.WasResolved());
 6033      Contract.Requires(resolutionContext != null);
 6034      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6035
 1438256036      if (expr.OptTypeArguments != null) {
 2494206037        foreach (var ty in expr.OptTypeArguments) {
 591956038          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 591956039        }
 239456040      }
 6041
 1198806042      Expression r = null;  // the resolved expression, if successful
 6043
 6044      // For 0:
 6045      TypeParameter tp;
 6046#if ASYNC_TASK_TYPES
 6047      // For 1:
 6048      Dictionary<string, MemberDecl> members;
 6049      // For 1 and 3:
 6050      MemberDecl member = null;
 6051#endif
 6052      // For 2:
 6053
 1198806054      tp = allTypeParameters.Find(expr.Name);
 1376806055      if (tp != null) {
 6056        // ----- 0. type parameter
 356006057        if (expr.OptTypeArguments == null) {
 178006058          r = new Resolver_IdentifierExpr(expr.tok, tp);
 178006059        } else {
 06060          reporter.Error(MessageSource.Resolver, expr.tok, "Type parameter expects no type arguments: {0}", expr.Name);
 06061        }
 6062#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6063      } else if (currentClass != null && classMembers.TryGetValue(currentClass, out members) && members.TryGetValue(expr
 6064        // ----- 1. member of the enclosing class
 6065        Expression receiver;
 6066        if (member.IsStatic) {
 6067          receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6068        } else {
 6069          if (!scope.AllowInstance) {
 6070            reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context");
 6071            // nevertheless, set "receiver" to a value so we can continue resolution
 6072          }
 6073          receiver = new ImplicitThisExpr(expr.tok);
 6074          receiver.Type = GetThisType(expr.tok, (ClassDecl)member.EnclosingClass);  // resolve here
 6075        }
 6076        r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodCal
 6077#endif
 2219606078      } else if (moduleInfo.TopLevels.TryGetValue(expr.Name, out var decl)) {
 6079        // ----- 2. Member of the enclosing module
 1020806080        if (decl is AmbiguousTopLevelDecl) {
 06081          var ad = (AmbiguousTopLevelDecl)decl;
 06082          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 1020806083        } else {
 6084          // We have found a module name or a type name, neither of which is a type expression. However, the NameSegment
 6085          // looking at may be followed by a further suffix that makes this into a type expresion. We postpone the rest 
 6086          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 6087          // or verifier, just to have a placeholder where we can recorded what we have found.
 1020806088          r = CreateResolver_IdentifierExpr(expr.tok, expr.Name, expr.OptTypeArguments, decl);
 1020806089        }
 6090
 6091#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6092      } else if (moduleInfo.StaticMembers.TryGetValue(expr.Name, out member)) {
 6093        // ----- 3. static member of the enclosing module
 6094        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 6095        if (ReallyAmbiguousThing(ref member)) {
 6096          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one of
 6097        } else {
 6098          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6099          r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodC
 6100        }
 6101#endif
 1020806102      } else {
 6103        // ----- None of the above
 06104        reporter.Error(MessageSource.Resolver, expr.tok, "Type or type parameter is not declared in this scope: {0} (did
 06105      }
 6106
 1198806107      if (r == null) {
 6108        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06109        expr.Type = new InferredTypeProxy();
 1198806110      } else {
 1198806111        expr.ResolvedExpression = r;
 1198806112        expr.Type = r.Type;
 1198806113      }
 1198806114    }
 6115
 6116    /// <summary>
 6117    /// To resolve "id" in expression "E . id", do:
 6118    ///  * If E denotes a module name M:
 6119    ///      0. If isLastNameSegment:
 6120    ///         Unambiguous constructor name of a datatype in module M (if two constructors have the same name, an error
 6121    ///         (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority
 6122    ///      1. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 6123    ///         (if two imported types have the same name, an error message is produced here)
 6124    ///      2. Static function or method of M._default
 6125    ///    (Note that in contrast to ResolveNameSegment, imported modules, etc. are ignored)
 6126    ///  * If E denotes a type:
 6127    ///      3. Look up id as a member of that type
 6128    ///  * If E denotes an expression:
 6129    ///      4. Let T be the type of E.  Look up id in T.
 6130    /// </summary>
 6131    /// <param name="expr"></param>
 6132    /// <param name="isLastNameSegment">Indicates that the ExprDotName is not directly enclosed in another ExprDotName e
 6133    /// <param name="args">If the ExprDotName is enclosed in an ApplySuffix, then these are the arguments.  The method r
 6134    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 6135    /// that incorporates these arguments.</param>
 6136    /// <param name="resolutionContext"></param>
 6137    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 6138    /// a Resolver_MethodCall.</param>
 89806139    Expression ResolveDotSuffix(ExprDotName expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext re
 6140      Contract.Requires(expr != null);
 6141      Contract.Requires(!expr.WasResolved());
 6142      Contract.Requires(resolutionContext != null);
 6143      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 6144
 6145      // resolve the LHS expression
 6146      // LHS should not be reveal lemma
 89806147      ModuleDecl shadowedImport = null;
 89806148      ResolutionContext nonRevealOpts = resolutionContext with { InReveal = false };
 149306149      if (expr.Lhs is NameSegment) {
 59506150        ResolveNameSegment((NameSegment)expr.Lhs, false, null, nonRevealOpts, false, true, out shadowedImport);
 97706151      } else if (expr.Lhs is ExprDotName) {
 7906152        ResolveDotSuffix((ExprDotName)expr.Lhs, false, null, nonRevealOpts, false);
 30306153      } else {
 22406154        ResolveExpression(expr.Lhs, nonRevealOpts);
 22406155      }
 6156
 89806157      if (expr.OptTypeArguments != null) {
 06158        foreach (var ty in expr.OptTypeArguments) {
 06159          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 06160        }
 06161      }
 6162
 89806163      Expression r = null;  // the resolved expression, if successful
 89806164      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 89806165      MemberDecl member = null;
 6166
 89806167      var name = resolutionContext.InReveal ? "reveal_" + expr.SuffixName : expr.SuffixName;
 89806168      if (!expr.Lhs.WasResolved()) {
 06169        return null;
 6170      }
 89806171      var lhs = expr.Lhs.Resolved;
 89806172      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06173        var ri = (Resolver_IdentifierExpr)lhs;
 06174        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 06175        sig = GetSignature(sig);
 6176        // For 0:
 6177        // For 1:
 6178
 06179        if (isLastNameSegment && sig.Ctors.TryGetValue(name, out var pair)) {
 6180          // ----- 0. datatype constructor
 06181          if (pair.Item2) {
 6182            // there is more than one constructor with this name
 06183            reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor in module {2
 06184          } else {
 06185            if (expr.OptTypeArguments != null) {
 06186              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06187            }
 06188            var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding
 06189            ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null);
 6190
 06191            if (args == null) {
 06192              r = rr;
 06193            } else {
 06194              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06195              rWithArgs = rr;
 06196            }
 06197          }
 06198        } else if (sig.TopLevels.TryGetValue(name, out var decl)) {
 6199          // ----- 1. Member of the specified module
 06200          if (decl is AmbiguousTopLevelDecl) {
 06201            var ad = (AmbiguousTopLevelDecl)decl;
 06202            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 06203          } else {
 6204            // We have found a module name or a type name, neither of which is an expression. However, the ExprDotName w
 6205            // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of
 6206            // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the c
 6207            // or verifier, just to have a placeholder where we can recorded what we have found.
 06208            if (!isLastNameSegment) {
 06209              if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 6210                // A possibly-null type C? was mentioned. But it does not have any further members. The program should h
 6211                // the name of the class, C. Report an error and continue.
 06212                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 06213              }
 06214            }
 06215            r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 06216          }
 06217        } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 6218          // ----- 2. static member of the specified module
 06219          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 06220          if (member is AmbiguousMemberDecl) {
 06221            var ambiguousMember = (AmbiguousMemberDecl)member;
 06222            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 06223          } else {
 06224            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (ClassDecl)member.EnclosingClass, false);
 06225            receiver.ContainerExpression = expr.Lhs;
 06226            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06227          }
 06228        } else {
 06229          reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 06230        }
 6231
 89806232      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 06233        var ri = (Resolver_IdentifierExpr)lhs;
 6234        // ----- 3. Look up name in type
 6235        // expand any synonyms
 06236        var ty = new UserDefinedType(expr.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs).NormalizeExpand();
 06237        if (ty.IsDatatype) {
 6238          // ----- LHS is a datatype
 06239          var dt = ty.AsDatatype;
 06240          if (dt.ConstructorsByName != null && dt.ConstructorsByName.TryGetValue(name, out var ctor)) {
 06241            if (expr.OptTypeArguments != null) {
 06242              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06243            }
 06244            var rr = new DatatypeValue(expr.tok, ctor.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>());
 06245            ResolveDatatypeValue(resolutionContext, rr, ctor.EnclosingDatatype, ty);
 06246            if (args == null) {
 06247              r = rr;
 06248            } else {
 06249              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06250              rWithArgs = rr;
 06251            }
 06252          }
 06253        }
 06254        var cd = r == null ? ty.AsTopLevelTypeWithMembersBypassInternalSynonym : null;
 06255        if (cd != null) {
 6256          // ----- LHS is a type with members
 06257          if (classMembers.TryGetValue(cd, out var members) && members.TryGetValue(name, out member)) {
 06258            if (!VisibleInScope(member)) {
 06259              reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' has not been imported in this scope and can
 06260            }
 06261            if (!member.IsStatic) {
 06262              reporter.Error(MessageSource.Resolver, expr.tok, "accessing member '{0}' requires an instance expression",
 6263              // nevertheless, continue creating an expression that approximates a correct one
 06264            }
 06265            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (UserDefinedType)ty.NormalizeExpand(), (TopLevelDeclWith
 06266            receiver.ContainerExpression = expr.Lhs;
 06267            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06268          }
 06269        }
 06270        if (r == null) {
 06271          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in {2} '{1}'", name, ri.Decl.Nam
 06272        }
 179606273      } else if (lhs != null) {
 6274        // ----- 4. Look up name in the type of the Lhs
 89806275        member = ResolveMember(expr.tok, expr.Lhs.Type, name, out var tentativeReceiverType);
 179606276        if (member != null) {
 6277          Expression receiver;
 179606278          if (!member.IsStatic) {
 89806279            receiver = expr.Lhs;
 89806280            AddAssignableConstraint(expr.tok, tentativeReceiverType, receiver.Type, "receiver type ({1}) does not have a
 89806281            r = ResolveExprDotCall(expr.tok, receiver, tentativeReceiverType, member, args, expr.OptTypeArguments, resol
 89806282          } else {
 06283            receiver = new StaticReceiverExpr(expr.tok, (UserDefinedType)tentativeReceiverType, (TopLevelDeclWithMembers
 06284            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06285          }
 89806286        }
 89806287      }
 6288
 89806289      if (r == null) {
 6290        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06291        expr.Type = new InferredTypeProxy();
 89806292      } else {
 89806293        CheckForAmbiguityInShadowedImportedModule(shadowedImport, name, expr.tok, useCompileSignatures, isLastNameSegmen
 89806294        expr.ResolvedExpression = r;
 89806295        expr.Type = r.Type;
 89806296      }
 89806297      return rWithArgs;
 89806298    }
 6299
 6300    /// <summary>
 6301    /// Check whether the name we just resolved may have been resolved differently if we didn't allow member `M.M` of
 6302    /// module `M` to shadow `M` when the user writes `import opened M`.  Raising an error in that case allowed us to
 6303    /// change the behavior of `import opened` without silently changing the meaning of existing programs.
 6304    /// (https://github.com/dafny-lang/dafny/issues/1996)
 6305    ///
 6306    /// Note the extra care for the constructor case, which is needed because the constructors of datatype `M.M` are
 6307    /// exposed through both `M` and `M.M`, without ambiguity.
 6308    /// </summary>
 6309    private void CheckForAmbiguityInShadowedImportedModule(ModuleDecl moduleDecl, string name,
 89806310      IToken tok, bool useCompileSignatures, bool isLastNameSegment) {
 89806311      if (moduleDecl != null && NameConflictsWithModuleContents(moduleDecl, name, useCompileSignatures, isLastNameSegmen
 06312        reporter.Error(MessageSource.Resolver, tok,
 06313          "Reference to member '{0}' is ambiguous: name '{1}' shadows an import-opened module of the same name, and "
 06314          + "both have a member '{0}'. To solve this issue, give a different name to the imported module using "
 06315          + "`import opened XYZ = ...` instead of `import opened ...`.",
 06316          name, moduleDecl.Name);
 06317      }
 89806318    }
 6319
 06320    private bool NameConflictsWithModuleContents(ModuleDecl moduleDecl, string name, bool useCompileSignatures, bool isL
 06321      var sig = GetSignature(moduleDecl.AccessibleSignature(useCompileSignatures));
 06322      return (
 06323        (isLastNameSegment
 06324         && sig.Ctors.GetValueOrDefault(name) is { Item1: var constructor, Item2: var ambiguous }
 06325         && !ambiguous && constructor.EnclosingDatatype.Name != moduleDecl.Name)
 06326        || sig.TopLevels.ContainsKey(name)
 06327        || sig.StaticMembers.ContainsKey(name)
 06328      );
 06329    }
 6330
 6331    Expression ResolveExprDotCall(IToken tok, Expression receiver, Type receiverTypeBound/*?*/,
 308006332      MemberDecl member, List<ActualBinding> args, List<Type> optTypeArguments, ResolutionContext resolutionContext, boo
 6333      Contract.Requires(tok != null);
 6334      Contract.Requires(receiver != null);
 6335      Contract.Requires(receiver.WasResolved());
 6336      Contract.Requires(member != null);
 6337      Contract.Requires(resolutionContext != null && resolutionContext.CodeContext != null);
 6338
 308006339      var rr = new MemberSelectExpr(tok, receiver, member.Name);
 308006340      rr.Member = member;
 6341
 6342      // Now, fill in rr.Type.  This requires taking into consideration the type parameters passed to the receiver's typ
 6343      // parameters used in this NameSegment/ExprDotName.
 6344      // Add to "subst" the type parameters given to the member's class/datatype
 308006345      rr.TypeApplication_AtEnclosingClass = new List<Type>();
 308006346      rr.TypeApplication_JustMember = new List<Type>();
 6347      Dictionary<TypeParameter, Type> subst;
 308006348      var rType = (receiverTypeBound ?? receiver.Type).NormalizeExpand();
 616006349      if (rType is UserDefinedType udt && udt.ResolvedClass != null) {
 308006350        subst = TypeParameter.SubstitutionMap(udt.ResolvedClass.TypeArgs, udt.TypeArgs);
 308006351        if (member.EnclosingClass == null) {
 6352          // this can happen for some special members, like real.Floor
 308006353        } else {
 308006354          rr.TypeApplication_AtEnclosingClass.AddRange(rType.AsParentType(member.EnclosingClass).TypeArgs);
 308006355        }
 308006356      } else {
 06357        var vtd = AsValuetypeDecl(rType);
 06358        if (vtd != null) {
 06359          Contract.Assert(vtd.TypeArgs.Count == rType.TypeArgs.Count);
 06360          subst = TypeParameter.SubstitutionMap(vtd.TypeArgs, rType.TypeArgs);
 06361          rr.TypeApplication_AtEnclosingClass.AddRange(rType.TypeArgs);
 06362        } else {
 06363          Contract.Assert(rType.TypeArgs.Count == 0);
 06364          subst = new Dictionary<TypeParameter, Type>();
 06365        }
 06366      }
 6367
 397806368      if (member is Field) {
 89806369        var field = (Field)member;
 89806370        if (optTypeArguments != null) {
 06371          reporter.Error(MessageSource.Resolver, tok, "a field ({0}) does not take any type arguments (got {1})", field.
 06372        }
 89806373        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 89806374        rr.Type = field.Type.Subst(subst);
 409706375      } else if (member is Function) {
 101706376        var fn = (Function)member;
 101706377        if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 06378          reporter.Error(MessageSource.Resolver, tok, "two-state function ('{0}') can only be called in a two-state cont
 06379        }
 101706380        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 101706381        if (optTypeArguments != null && suppliedTypeArguments != fn.TypeArgs.Count) {
 06382          reporter.Error(MessageSource.Resolver, tok, "function '{0}' expects {1} type argument{2} (got {3})",
 06383            member.Name, fn.TypeArgs.Count, Util.Plural(fn.TypeArgs.Count), suppliedTypeArguments);
 06384        }
 352506385        for (int i = 0; i < fn.TypeArgs.Count; i++) {
 49706386          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 49706387          rr.TypeApplication_JustMember.Add(ta);
 49706388          subst.Add(fn.TypeArgs[i], ta);
 49706389        }
 101706390        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 101706391        rr.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 218206392      } else {
 6393        // the member is a method
 116506394        var m = (Method)member;
 116506395        if (!allowMethodCall) {
 6396          // it's a method and method calls are not allowed in the given context
 06397          reporter.Error(MessageSource.Resolver, tok, "expression is not allowed to invoke a {0} ({1})", member.WhatKind
 06398        }
 116506399        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 116506400        if (optTypeArguments != null && suppliedTypeArguments != m.TypeArgs.Count) {
 06401          reporter.Error(MessageSource.Resolver, tok, "method '{0}' expects {1} type argument{2} (got {3})",
 06402            member.Name, m.TypeArgs.Count, Util.Plural(m.TypeArgs.Count), suppliedTypeArguments);
 06403        }
 233006404        for (int i = 0; i < m.TypeArgs.Count; i++) {
 06405          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 06406          rr.TypeApplication_JustMember.Add(ta);
 06407          subst.Add(m.TypeArgs[i], ta);
 06408        }
 116506409        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 290706410        rr.ResolvedOutparameterTypes = m.Outs.ConvertAll(f => f.Type.Subst(subst));
 116506411        rr.Type = new InferredTypeProxy();  // fill in this field, in order to make "rr" resolved
 116506412      }
 308006413      return rr;
 308006414    }
 6415
 204406416    public MethodCallInformation ResolveApplySuffix(ApplySuffix e, ResolutionContext resolutionContext, bool allowMethod
 6417      Contract.Requires(e != null);
 6418      Contract.Requires(resolutionContext != null);
 6419      Contract.Ensures(Contract.Result<MethodCallInformation>() == null || allowMethodCall);
 204406420      Expression r = null;  // upon success, the expression to which the ApplySuffix resolves
 204406421      var errorCount = reporter.Count(ErrorLevel.Error);
 400306422      if (e.Lhs is NameSegment) {
 195906423        r = ResolveNameSegment((NameSegment)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall
 6424        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 208806425      } else if (e.Lhs is ExprDotName) {
 4406426        r = ResolveDotSuffix((ExprDotName)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall);
 6427        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 8506428      } else {
 4106429        ResolveExpression(e.Lhs, resolutionContext);
 4106430      }
 204406431      if (e.Lhs.Type == null) {
 6432        // some error had been detected during the attempted resolution of e.Lhs
 06433        e.Lhs.Type = new InferredTypeProxy();
 06434      }
 204406435      Label atLabel = null;
 204406436      if (e.AtTok != null) {
 06437        atLabel = DominatingStatementLabels.Find(e.AtTok.val);
 06438        if (atLabel == null) {
 06439          reporter.Error(MessageSource.Resolver, e.AtTok, "no label '{0}' in scope at this time", e.AtTok.val);
 06440        }
 06441      }
 408806442      if (r == null) {
 204406443        var improvedType = PartiallyResolveTypeForMemberSelection(e.Lhs.tok, e.Lhs.Type, "_#apply");
 204406444        var fnType = improvedType.AsArrowType;
 320906445        if (fnType == null) {
 116506446          var lhs = e.Lhs.Resolved;
 116506447          if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06448            reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a function", ((Resolver_Ident
 116506449          } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 06450            var ri = (Resolver_IdentifierExpr)lhs;
 06451            reporter.Error(MessageSource.Resolver, e.tok, "name of {0} ({1}) is used as a function", ri.Decl.WhatKind, r
 116506452          } else {
 233006453            if (lhs is MemberSelectExpr mse && mse.Member is Method) {
 116506454              if (atLabel != null) {
 06455                Contract.Assert(mse != null); // assured by the parser
 06456                if (mse.Member is TwoStateLemma) {
 06457                  mse.AtLabel = atLabel;
 06458                } else {
 06459                  reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state lemma")
 06460                }
 06461              }
 233006462              if (allowMethodCall) {
 116506463                Contract.Assert(!e.Bindings.WasResolved); // we expect that .Bindings has not yet been processed, so we 
 116506464                var tok = Options.Get(DafnyConsolePrinter.ShowSnippets) ? e.RangeToken.ToToken() : e.tok;
 116506465                var cRhs = new MethodCallInformation(tok, mse, e.Bindings.ArgumentBindings);
 116506466                return cRhs;
 06467              } else {
 06468                reporter.Error(MessageSource.Resolver, e.tok, "{0} call is not allowed to be used in an expression conte
 06469              }
 06470            } else if (lhs != null) {  // if e.Lhs.Resolved is null, then e.Lhs was not successfully resolved and an err
 06471              reporter.Error(MessageSource.Resolver, e.tok, "non-function expression (of type {0}) is called with parame
 06472            }
 06473          }
 6474          // resolve the arguments, even in the presence of the errors above
 06475          foreach (var binding in e.Bindings.ArgumentBindings) {
 06476            ResolveExpression(binding.Actual, resolutionContext);
 06477          }
 87906478        } else {
 87906479          var mse = e.Lhs is NameSegment || e.Lhs is ExprDotName ? e.Lhs.Resolved as MemberSelectExpr : null;
 87906480          var callee = mse == null ? null : mse.Member as Function;
 87906481          if (atLabel != null && !(callee is TwoStateFunction)) {
 06482            reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state function");
 06483            atLabel = null;
 06484          }
 167306485          if (callee != null) {
 6486            // produce a FunctionCallExpr instead of an ApplyExpr(MemberSelectExpr)
 79406487            var rr = new FunctionCallExpr(e.Lhs.tok, callee.Name, mse.Obj, e.tok, e.CloseParen, e.Bindings, atLabel) {
 79406488              Function = callee,
 79406489              TypeApplication_AtEnclosingClass = mse.TypeApplication_AtEnclosingClass,
 79406490              TypeApplication_JustFunction = mse.TypeApplication_JustMember
 79406491            };
 79406492            var typeMap = BuildTypeArgumentSubstitute(mse.TypeArgumentSubstitutionsAtMemberDeclaration());
 79406493            ResolveActualParameters(rr.Bindings, callee.Formals, e.tok, callee, resolutionContext, typeMap, callee.IsSta
 79406494            rr.Type = callee.ResultType.Subst(typeMap);
 158806495            if (errorCount == reporter.Count(ErrorLevel.Error)) {
 79406496              Contract.Assert(!(mse.Obj is StaticReceiverExpr) || callee.IsStatic);  // this should have been checked al
 79406497              Contract.Assert(callee.Formals.Count == rr.Args.Count);  // this should have been checked already
 79406498            }
 79406499            r = rr;
 87906500          } else {
 6501            List<Formal> formals;
 8506502            if (callee != null) {
 06503              formals = callee.Formals;
 8506504            } else {
 8506505              formals = new List<Formal>();
 77006506              for (var i = 0; i < fnType.Args.Count; i++) {
 20006507                var argType = fnType.Args[i];
 20006508                var formal = new ImplicitFormal(e.tok, "_#p" + i, argType, true, false);
 20006509                formals.Add(formal);
 20006510              }
 8506511            }
 8506512            ResolveActualParameters(e.Bindings, formals, e.tok, fnType, resolutionContext, new Dictionary<TypeParameter,
 8506513            r = new ApplyExpr(e.Lhs.tok, e.Lhs, e.Args, e.CloseParen);
 8506514            r.Type = fnType.Result;
 8506515          }
 87906516        }
 87906517      }
 87906518      if (r == null) {
 6519        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06520        e.Type = new InferredTypeProxy();
 87906521      } else {
 87906522        e.ResolvedExpression = r;
 87906523        e.Type = r.Type;
 87906524      }
 87906525      return null;
 204406526    }
 6527
 6528    /// <summary>
 6529    /// the return value is false iff there is an error in resolving the datatype value;
 6530    /// if there is an error then an error message is emitted iff complain is true
 6531    /// </summary>
 1585106532    private bool ResolveDatatypeValue(ResolutionContext resolutionContext, DatatypeValue dtv, DatatypeDecl dt, Type ty, 
 6533      Contract.Requires(resolutionContext != null);
 6534      Contract.Requires(dtv != null);
 6535      Contract.Requires(dt != null);
 6536      Contract.Requires(ty == null || (ty.AsDatatype == dt && ty.TypeArgs.Count == dt.TypeArgs.Count));
 6537
 1585106538      var ok = true;
 1585106539      var gt = new List<Type>(dt.TypeArgs.Count);
 1585106540      var subst = new Dictionary<TypeParameter, Type>();
 12127006541      for (int i = 0; i < dt.TypeArgs.Count; i++) {
 2985606542        Type t = ty == null ? new InferredTypeProxy() : ty.TypeArgs[i];
 2985606543        gt.Add(t);
 2985606544        dtv.InferredTypeArgs.Add(t);
 2985606545        subst.Add(dt.TypeArgs[i], t);
 2985606546      }
 6547      // Construct a resolved type directly, as we know the declaration is dt.
 1585106548      dtv.Type = new UserDefinedType(dtv.tok, dt.Name, dt, gt);
 6549
 1585106550      if (!dt.ConstructorsByName.TryGetValue(dtv.MemberName, out var ctor)) {
 06551        ok = false;
 06552        if (complain) {
 06553          reporter.Error(MessageSource.Resolver, dtv.tok, "undeclared constructor {0} in datatype {1}", dtv.MemberName, 
 06554        }
 1585106555      } else {
 1585106556        Contract.Assert(ctor != null);  // follows from postcondition of TryGetValue
 1585106557        dtv.Ctor = ctor;
 1585106558      }
 3170206559      if (complain && ctor != null) {
 1585106560        ResolveActualParameters(dtv.Bindings, ctor.Formals, dtv.tok, ctor, resolutionContext, subst, null);
 1585106561      } else {
 6562        // still resolve the expressions
 06563        foreach (var binding in dtv.Bindings.ArgumentBindings) {
 06564          ResolveExpression(binding.Actual, resolutionContext);
 06565        }
 06566        dtv.Bindings.AcceptArgumentExpressionsAsExactParameterList();
 06567      }
 6568
 1585106569      return ok && ctor.Formals.Count == dtv.Arguments.Count;
 1585106570    }
 6571
 06572    public void ResolveFunctionCallExpr(FunctionCallExpr e, ResolutionContext resolutionContext) {
 6573      Contract.Requires(e != null);
 6574      Contract.Requires(e.Type == null);  // should not have been type checked before
 6575
 06576      ResolveReceiver(e.Receiver, resolutionContext);
 06577      Contract.Assert(e.Receiver.Type != null);  // follows from postcondition of ResolveExpression
 6578
 06579      var member = ResolveMember(e.tok, e.Receiver.Type, e.Name, out var tentativeReceiverType);
 6580#if !NO_WORK_TO_BE_DONE
 06581      var ctype = (UserDefinedType)tentativeReceiverType;
 6582#endif
 06583      if (member == null) {
 6584        // error has already been reported by ResolveMember
 06585      } else if (member is Method) {
 06586        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} refers to a method, but only functions can be 
 06587      } else if (!(member is Function)) {
 06588        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} does not refer to a function", e.Name, cce.Non
 06589      } else {
 06590        Function function = (Function)member;
 06591        e.Function = function;
 06592        if (function is TwoStateFunction && !resolutionContext.IsTwoState) {
 06593          reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context");
 06594        }
 06595        if (e.Receiver is StaticReceiverExpr && !function.IsStatic) {
 06596          reporter.Error(MessageSource.Resolver, e, "an instance function must be selected via an object, not just a cla
 06597        }
 06598        Contract.Assert(ctype != null);  // follows from postcondition of ResolveMember
 06599        if (!function.IsStatic) {
 06600          if (!scope.AllowInstance && e.Receiver is ThisExpr) {
 6601            // The call really needs an instance, but that instance is given as 'this', which is not
 6602            // available in this context.  In most cases, occurrences of 'this' inside e.Receiver would
 6603            // have been caught in the recursive call to resolve e.Receiver, but not the specific case
 6604            // of e.Receiver being 'this' (explicitly or implicitly), for that case needs to be allowed
 6605            // in the event that a static function calls another static function (and note that we need the
 6606            // type of the receiver in order to find the method, so we could not have made this check
 6607            // earlier).
 06608            reporter.Error(MessageSource.Resolver, e.Receiver, "'this' is not allowed in a 'static' context");
 06609          } else if (e.Receiver is StaticReceiverExpr) {
 06610            reporter.Error(MessageSource.Resolver, e.Receiver, "call to instance function requires an instance");
 06611          }
 06612        }
 6613        // build the type substitution map
 06614        var typeMap = new Dictionary<TypeParameter, Type>();
 06615        for (int i = 0; i < ctype.TypeArgs.Count; i++) {
 06616          typeMap.Add(ctype.ResolvedClass.TypeArgs[i], ctype.TypeArgs[i]);
 06617        }
 06618        var typeThatEnclosesMember = ctype.AsParentType(member.EnclosingClass);
 06619        e.TypeApplication_AtEnclosingClass = new List<Type>();
 06620        for (int i = 0; i < typeThatEnclosesMember.TypeArgs.Count; i++) {
 06621          e.TypeApplication_AtEnclosingClass.Add(typeThatEnclosesMember.TypeArgs[i]);
 06622        }
 06623        e.TypeApplication_JustFunction = new List<Type>();
 06624        foreach (TypeParameter p in function.TypeArgs) {
 06625          var ty = new ParamTypeProxy(p);
 06626          typeMap.Add(p, ty);
 06627          e.TypeApplication_JustFunction.Add(ty);
 06628        }
 06629        Dictionary<TypeParameter, Type> subst = BuildTypeArgumentSubstitute(typeMap);
 6630
 6631        // type check the arguments
 06632        ResolveActualParameters(e.Bindings, function.Formals, e.tok, function, resolutionContext, subst, function.IsStat
 6633
 06634        e.Type = function.ResultType.Subst(subst).NormalizeExpand();
 06635      }
 06636    }
 6637
 06638    void ResolveReceiver(Expression expr, ResolutionContext resolutionContext) {
 6639      Contract.Requires(expr != null);
 6640      Contract.Ensures(expr.Type != null);
 6641
 06642      if (expr is ThisExpr && !expr.WasResolved()) {
 6643        // Allow 'this' here, regardless of scope.AllowInstance.  The caller is responsible for
 6644        // making sure 'this' does not really get used when it's not available.
 06645        Contract.Assume(currentClass != null);  // this is really a precondition, in this case
 06646        expr.Type = GetThisType(expr.tok, currentClass);
 06647      } else {
 06648        ResolveExpression(expr, resolutionContext);
 06649      }
 06650    }
 6651
 137806652    void ResolveSeqSelectExpr(SeqSelectExpr e, ResolutionContext resolutionContext) {
 6653      Contract.Requires(e != null);
 137806654      if (e.Type != null) {
 6655        // already resolved
 06656        return;
 6657      }
 6658
 137806659      ResolveExpression(e.Seq, resolutionContext);
 137806660      Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 6661
 151006662      if (e.SelectOne) {
 13206663        AddXConstraint(e.tok, "Indexable", e.Seq.Type, "element selection requires a sequence, array, multiset, or map (
 13206664        ResolveExpression(e.E0, resolutionContext);
 13206665        AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got {1
 13206666        Contract.Assert(e.E1 == null);
 13206667        e.Type = new InferredTypeProxy() { KeepConstraints = true };
 13206668        AddXConstraint(e.tok, "ContainerResult",
 13206669          e.Seq.Type, e.Type,
 13206670          new SeqSelectOneErrorMsg(e.tok, e.Seq.Type, e.Type));
 137806671      } else {
 124606672        AddXConstraint(e.tok, "MultiIndexable", e.Seq.Type, "multi-selection of elements requires a sequence or array (g
 204706673        if (e.E0 != null) {
 80106674          ResolveExpression(e.E0, resolutionContext);
 80106675          AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got 
 80106676          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E0.Type, e.E0, "wrong number of indices for multi-sele
 80106677        }
 222506678        if (e.E1 != null) {
 97906679          ResolveExpression(e.E1, resolutionContext);
 97906680          AddXConstraint(e.E1.tok, "ContainerIndex", e.Seq.Type, e.E1.Type, "incorrect type for selection into {0} (got 
 97906681          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E1.Type, e.E1, "wrong number of indices for multi-sele
 97906682        }
 124606683        var resultType = new InferredTypeProxy() { KeepConstraints = true };
 124606684        e.Type = new SeqType(resultType);
 124606685        AddXConstraint(e.tok, "ContainerResult", e.Seq.Type, resultType, "multi-selection has type {0} which is incompat
 124606686      }
 137806687    }
 6688
 6689  }
 6690
 6691  public class MethodCallInformation {
 6692    public readonly IToken Tok;
 6693    public readonly MemberSelectExpr Callee;
 6694    public readonly List<ActualBinding> ActualParameters;
 6695
 6696    [ContractInvariantMethod]
 6697    void ObjectInvariant() {
 6698      Contract.Invariant(Tok != null);
 6699      Contract.Invariant(Callee != null);
 6700      Contract.Invariant(Callee.Member is Method);
 6701      Contract.Invariant(ActualParameters != null);
 6702    }
 6703
 6704    public MethodCallInformation(IToken tok, MemberSelectExpr callee, List<ActualBinding> actualParameters) {
 6705      Contract.Requires(tok != null);
 6706      Contract.Requires(callee != null);
 6707      Contract.Requires(callee.Member is Method);
 6708      Contract.Requires(actualParameters != null);
 6709      this.Tok = tok;
 6710      this.Callee = callee;
 6711      this.ActualParameters = actualParameters;
 6712    }
 6713  }
 6714}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/Resolver.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 4// Copyright by the contributors to the Dafny Project
 5// SPDX-License-Identifier: MIT
 6//
 7//-----------------------------------------------------------------------------
 8using System;
 9using System.Collections.Generic;
 10using System.Linq;
 11using System.Numerics;
 12using System.Diagnostics.Contracts;
 13using System.IO;
 14using System.Reflection;
 15using JetBrains.Annotations;
 16using Microsoft.BaseTypes;
 17using Microsoft.Boogie;
 18using Microsoft.CodeAnalysis.CSharp.Syntax;
 19using Microsoft.Dafny.Plugins;
 20using static Microsoft.Dafny.ErrorRegistry;
 21
 22namespace Microsoft.Dafny {
 23  interface ICanResolve {
 24    void Resolve(Resolver resolver, ResolutionContext context);
 25  }
 26
 27  public enum FrameExpressionUse { Reads, Modifies, Unchanged }
 28
 29  public partial class Resolver {
 14681597030    public DafnyOptions Options { get; }
 31    public readonly BuiltIns builtIns;
 32
 33    public ErrorReporter reporter;
 44534    ModuleSignature moduleInfo = null;
 35
 118647536    public ErrorReporter Reporter => reporter;
 16281537    public List<TypeConstraint.ErrorMsg> TypeConstraintErrorsToBeReported { get; } = new();
 38
 039    private bool RevealedInScope(Declaration d) {
 40      Contract.Requires(d != null);
 41      Contract.Requires(moduleInfo != null);
 42      Contract.Requires(moduleInfo.VisibilityScope != null);
 43
 044      return useCompileSignatures || d.IsRevealedInScope(moduleInfo.VisibilityScope);
 045    }
 46
 5291047    private bool VisibleInScope(Declaration d) {
 48      Contract.Requires(d != null);
 49      Contract.Requires(moduleInfo != null);
 50      Contract.Requires(moduleInfo.VisibilityScope != null);
 51
 5291052      return useCompileSignatures || d.IsVisibleInScope(moduleInfo.VisibilityScope);
 5291053    }
 54
 44555    public FreshIdGenerator defaultTempVarIdGenerator = new FreshIdGenerator();
 56
 057    public string FreshTempVarName(string prefix, ICodeContext context) {
 058      var gen = context is Declaration decl ? decl.IdGenerator : defaultTempVarIdGenerator;
 059      var freshTempVarName = gen.FreshId(prefix);
 060      return freshTempVarName;
 061    }
 62
 63    interface IAmbiguousThing<Thing> {
 64      /// <summary>
 65      /// Returns a plural number of non-null Thing's
 66      /// </summary>
 67      ISet<Thing> Pool { get; }
 68    }
 69
 70    class AmbiguousThingHelper<Thing> where Thing : class {
 071      public static Thing Create(ModuleDefinition m, Thing a, Thing b, IEqualityComparer<Thing> eq, out ISet<Thing> s) {
 72        Contract.Requires(a != null);
 73        Contract.Requires(b != null);
 74        Contract.Requires(eq != null);
 75        Contract.Ensures(Contract.Result<Thing>() != null ||
 76                         Contract.ValueAtReturn(out s) != null || 2 <= Contract.ValueAtReturn(out s).Count);
 077        s = null;
 078        if (eq.Equals(a, b)) {
 079          return a;
 80        }
 81
 082        ISet<Thing> sa = a is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)a).Pool : new HashSet<Thing>() { a };
 083        ISet<Thing> sb = b is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)b).Pool : new HashSet<Thing>() { b };
 084        var union = new HashSet<Thing>(sa.Union(sb, eq));
 085        if (sa.Count == union.Count) {
 86          // sb is a subset of sa
 087          return a;
 088        } else if (sb.Count == union.Count) {
 89          // sa is a subset of sb
 090          return b;
 091        } else {
 092          s = union;
 093          Contract.Assert(2 <= s.Count);
 094          return null;
 95        }
 096      }
 97
 098      public static string Name(ISet<Thing> s, Func<Thing, string> name) {
 99        Contract.Requires(s != null);
 100        Contract.Requires(s.Count != 0);
 0101        string nm = null;
 0102        foreach (var thing in s) {
 0103          string n = name(thing);
 0104          if (nm == null) {
 0105            nm = n;
 0106          } else {
 0107            nm += "/" + n;
 0108          }
 0109        }
 110
 0111        return nm;
 0112      }
 113
 0114      public static string ModuleNames(IAmbiguousThing<Thing> amb, Func<Thing, string> moduleName) {
 115        Contract.Requires(amb != null);
 116        Contract.Ensures(Contract.Result<string>() != null);
 0117        string nm = null;
 0118        foreach (var d in amb.Pool) {
 0119          if (nm == null) {
 0120            nm = moduleName(d);
 0121          } else {
 0122            nm += ", " + moduleName(d);
 0123          }
 0124        }
 125
 0126        return nm;
 0127      }
 128    }
 129
 130    public class AmbiguousTopLevelDecl : TopLevelDecl, IAmbiguousThing<TopLevelDecl> // only used with "classes"
 131    {
 0132      public static TopLevelDecl Create(ModuleDefinition m, TopLevelDecl a, TopLevelDecl b) {
 0133        var t = AmbiguousThingHelper<TopLevelDecl>.Create(m, a, b, new Eq(), out var s);
 0134        return t ?? new AmbiguousTopLevelDecl(m, AmbiguousThingHelper<TopLevelDecl>.Name(s, tld => tld.Name), s);
 0135      }
 136
 137      class Eq : IEqualityComparer<TopLevelDecl> {
 0138        public bool Equals(TopLevelDecl d0, TopLevelDecl d1) {
 139          // We'd like to resolve any AliasModuleDecl to whatever module they refer to.
 140          // It seems that the only way to do that is to look at alias.Signature.ModuleDef,
 141          // but that is a ModuleDefinition, which is not a TopLevelDecl.  Therefore, we
 142          // convert to a ModuleDefinition anything that might refer to something that an
 143          // AliasModuleDecl can refer to; this is AliasModuleDecl and LiteralModuleDecl.
 0144          object a = d0 is ModuleDecl ? ((ModuleDecl)d0).Dereference() : d0;
 0145          object b = d1 is ModuleDecl ? ((ModuleDecl)d1).Dereference() : d1;
 0146          return a == b;
 0147        }
 148
 0149        public int GetHashCode(TopLevelDecl d) {
 0150          object a = d is ModuleDecl ? ((ModuleDecl)d).Dereference() : d;
 0151          return a.GetHashCode();
 0152        }
 153      }
 154
 155      public override string WhatKind {
 0156        get { return Pool.First().WhatKind; }
 157      }
 158
 0159      readonly ISet<TopLevelDecl> Pool = new HashSet<TopLevelDecl>();
 160
 161      ISet<TopLevelDecl> IAmbiguousThing<TopLevelDecl>.Pool {
 0162        get { return Pool; }
 163      }
 164
 165      private AmbiguousTopLevelDecl(ModuleDefinition m, string name, ISet<TopLevelDecl> pool)
 0166        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), m, new List<TypeParameter>(), null, fal
 167        Contract.Requires(name != null);
 168        Contract.Requires(pool != null && 2 <= pool.Count);
 0169        Pool = pool;
 0170      }
 171
 0172      public string ModuleNames() {
 0173        return AmbiguousThingHelper<TopLevelDecl>.ModuleNames(this, d => d.EnclosingModuleDefinition.Name);
 0174      }
 175    }
 176
 177    class AmbiguousMemberDecl : MemberDecl, IAmbiguousThing<MemberDecl> // only used with "classes"
 178    {
 0179      public static MemberDecl Create(ModuleDefinition m, MemberDecl a, MemberDecl b) {
 180        ISet<MemberDecl> s;
 0181        var t = AmbiguousThingHelper<MemberDecl>.Create(m, a, b, new Eq(), out s);
 0182        return t ?? new AmbiguousMemberDecl(m, AmbiguousThingHelper<MemberDecl>.Name(s, member => member.Name), s);
 0183      }
 184
 185      class Eq : IEqualityComparer<MemberDecl> {
 0186        public bool Equals(MemberDecl d0, MemberDecl d1) {
 0187          return d0 == d1;
 0188        }
 189
 0190        public int GetHashCode(MemberDecl d) {
 0191          return d.GetHashCode();
 0192        }
 193      }
 194
 195      public override string WhatKind {
 0196        get { return Pool.First().WhatKind; }
 197      }
 198
 0199      readonly ISet<MemberDecl> Pool = new HashSet<MemberDecl>();
 200
 201      ISet<MemberDecl> IAmbiguousThing<MemberDecl>.Pool {
 0202        get { return Pool; }
 203      }
 204
 205      private AmbiguousMemberDecl(ModuleDefinition m, string name, ISet<MemberDecl> pool)
 0206        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), true, pool.First().IsGhost, null, false
 207        Contract.Requires(name != null);
 208        Contract.Requires(pool != null && 2 <= pool.Count);
 0209        Pool = pool;
 0210      }
 211
 0212      public string ModuleNames() {
 0213        return AmbiguousThingHelper<MemberDecl>.ModuleNames(this, d => d.EnclosingClass.EnclosingModuleDefinition.Name);
 0214      }
 215    }
 216
 445217    readonly HashSet<RevealableTypeDecl> revealableTypes = new HashSet<RevealableTypeDecl>();
 218    //types that have been seen by the resolver - used for constraining type inference during exports
 219
 445220    public readonly Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>> classMembers =
 445221      new Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>>();
 222
 223    enum ValuetypeVariety {
 224      Bool = 0,
 225      Int,
 226      Real,
 227      BigOrdinal,
 228      Bitvector,
 229      Map,
 230      IMap,
 231      None
 232    } // note, these are ordered, so they can be used as indices into valuetypeDecls
 233
 234    internal readonly ValuetypeDecl[] valuetypeDecls;
 235    private Dictionary<TypeParameter, Type> SelfTypeSubstitution;
 445236    readonly Graph<ModuleDecl> dependencies = new Graph<ModuleDecl>();
 445237    private ModuleSignature systemNameInfo = null;
 445238    private bool useCompileSignatures = false;
 239
 240    private List<IRewriter> rewriters;
 241    private RefinementTransformer refinementTransformer;
 242
 0243    public Resolver(DafnyOptions options) {
 0244      Options = options;
 0245    }
 246
 890247    public Resolver(Program prog) {
 445248      Options = prog.Options;
 249
 445250      allTypeParameters = new Scope<TypeParameter>(Options);
 445251      scope = new Scope<IVariable>(Options);
 445252      enclosingStatementLabels = new Scope<Statement>(Options);
 445253      DominatingStatementLabels = new Scope<Label>(Options);
 254
 255      Contract.Requires(prog != null);
 256
 445257      builtIns = prog.BuiltIns;
 445258      reporter = prog.Reporter;
 259
 260      // Map#Items relies on the two destructors for 2-tuples
 445261      builtIns.TupleType(Token.NoToken, 2, true);
 262      // Several methods and fields rely on 1-argument arrow types
 445263      builtIns.CreateArrowTypeDecl(1);
 264
 445265      valuetypeDecls = new ValuetypeDecl[] {
 8980266        new ValuetypeDecl("bool", builtIns.SystemModule, t => t.IsBoolType, typeArgs => Type.Bool),
 8980267        new ValuetypeDecl("int", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Int), typeArgs => T
 8980268        new ValuetypeDecl("real", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Real), typeArgs =>
 8980269        new ValuetypeDecl("ORDINAL", builtIns.SystemModule, t => t.IsBigOrdinalType, typeArgs => Type.BigOrdinal),
 8980270        new ValuetypeDecl("_bv", builtIns.SystemModule, t => t.IsBitVectorType, null), // "_bv" represents a family of c
 445271        new ValuetypeDecl("map", builtIns.SystemModule,
 445272          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Strict , TypeParameter.T
 8980273          t => t.IsMapType, typeArgs => new MapType(true, typeArgs[0], typeArgs[1])),
 445274        new ValuetypeDecl("imap", builtIns.SystemModule,
 445275          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Permissive , TypeParamet
 8980276          t => t.IsIMapType, typeArgs => new MapType(false, typeArgs[0], typeArgs[1]))
 445277      };
 445278      builtIns.SystemModule.TopLevelDecls.AddRange(valuetypeDecls);
 279      // Resolution error handling relies on being able to get to the 0-tuple declaration
 445280      builtIns.TupleType(Token.NoToken, 0, true);
 281
 282      // Populate the members of the basic types
 283
 4895284      void AddMember(MemberDecl member, ValuetypeVariety valuetypeVariety) {
 4895285        var enclosingType = valuetypeDecls[(int)valuetypeVariety];
 4895286        member.EnclosingClass = enclosingType;
 4895287        member.AddVisibilityScope(prog.BuiltIns.SystemModule.VisibilityScope, false);
 4895288        enclosingType.Members.Add(member.Name, member);
 4895289      }
 290
 445291      var floor = new SpecialField(RangeToken.NoToken, "Floor", SpecialField.ID.Floor, null, false, false, false, Type.I
 445292      AddMember(floor, ValuetypeVariety.Real);
 293
 445294      var isLimit = new SpecialField(RangeToken.NoToken, "IsLimit", SpecialField.ID.IsLimit, null, false, false, false, 
 445295      AddMember(isLimit, ValuetypeVariety.BigOrdinal);
 296
 445297      var isSucc = new SpecialField(RangeToken.NoToken, "IsSucc", SpecialField.ID.IsSucc, null, false, false, false, Typ
 445298      AddMember(isSucc, ValuetypeVariety.BigOrdinal);
 299
 445300      var limitOffset = new SpecialField(RangeToken.NoToken, "Offset", SpecialField.ID.Offset, null, false, false, false
 445301      AddMember(limitOffset, ValuetypeVariety.BigOrdinal);
 445302      builtIns.ORDINAL_Offset = limitOffset;
 303
 445304      var isNat = new SpecialField(RangeToken.NoToken, "IsNat", SpecialField.ID.IsNat, null, false, false, false, Type.B
 445305      AddMember(isNat, ValuetypeVariety.BigOrdinal);
 306
 307      // Add "Keys", "Values", and "Items" to map, imap
 4005308      foreach (var typeVariety in new[] { ValuetypeVariety.Map, ValuetypeVariety.IMap }) {
 890309        var vtd = valuetypeDecls[(int)typeVariety];
 890310        var isFinite = typeVariety == ValuetypeVariety.Map;
 311
 890312        var r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[0]));
 890313        var keys = new SpecialField(RangeToken.NoToken, "Keys", SpecialField.ID.Keys, null, false, false, false, r, null
 314
 890315        r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[1]));
 890316        var values = new SpecialField(RangeToken.NoToken, "Values", SpecialField.ID.Values, null, false, false, false, r
 317
 2670318        var gt = vtd.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 890319        var dt = builtIns.TupleType(Token.NoToken, 2, true);
 890320        var tupleType = new UserDefinedType(Token.NoToken, dt.Name, dt, gt);
 890321        r = new SetType(isFinite, tupleType);
 890322        var items = new SpecialField(RangeToken.NoToken, "Items", SpecialField.ID.Items, null, false, false, false, r, n
 323
 10680324        foreach (var memb in new[] { keys, values, items }) {
 2670325          AddMember(memb, typeVariety);
 2670326        }
 890327      }
 328
 329      // The result type of the following bitvector methods is the type of the bitvector itself. However, we're represen
 330      // a family of types rolled up in one ValuetypeDecl. Therefore, we use the special SelfType as the result type.
 445331      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateLeft", new SelfType());
 445332      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateRight", new SelfType());
 445333    }
 334
 890335    public void AddRotateMember(ValuetypeDecl enclosingType, string name, Type resultType) {
 890336      var formals = new List<Formal> { new Formal(Token.NoToken, "w", Type.Nat(), true, false, null, false) };
 890337      var rotateMember = new SpecialFunction(RangeToken.NoToken, name, builtIns.SystemModule, false, false,
 890338        new List<TypeParameter>(), formals, resultType,
 890339        new List<AttributedExpression>(), new List<FrameExpression>(), new List<AttributedExpression>(),
 890340        new Specification<Expression>(new List<Expression>(), null), null, null, null);
 890341      rotateMember.EnclosingClass = enclosingType;
 890342      rotateMember.AddVisibilityScope(builtIns.SystemModule.VisibilityScope, false);
 890343      enclosingType.Members.Add(name, rotateMember);
 890344    }
 345
 346    [ContractInvariantMethod]
 0347    void ObjectInvariant() {
 348      Contract.Invariant(builtIns != null);
 349      Contract.Invariant(cce.NonNullElements(dependencies.GetVertices()));
 350      Contract.Invariant(cce.NonNullDictionaryAndValues(classMembers) && Contract.ForAll(classMembers.Values, v => cce.N
 0351    }
 352
 0353    public ValuetypeDecl AsValuetypeDecl(Type t) {
 354      Contract.Requires(t != null);
 0355      foreach (var vtd in valuetypeDecls) {
 0356        if (vtd.IsThisType(t)) {
 0357          return vtd;
 358        }
 0359      }
 0360      return null;
 0361    }
 362
 363    /// <summary>
 364    /// Check that now two modules that are being compiled have the same CompileName.
 365    ///
 366    /// This could happen if they are given the same name using the 'extern' declaration modifier.
 367    /// </summary>
 368    /// <param name="prog">The Dafny program being compiled.</param>
 445369    void CheckDupModuleNames(Program prog) {
 370      // Check that none of the modules have the same CompileName.
 445371      Dictionary<string, ModuleDefinition> compileNameMap = new Dictionary<string, ModuleDefinition>();
 4005372      foreach (ModuleDefinition m in prog.CompileModules) {
 890373        var compileIt = true;
 890374        Attributes.ContainsBool(m.Attributes, "compile", ref compileIt);
 890375        if (m.IsAbstract || !compileIt) {
 376          // the purpose of an abstract module is to skip compilation
 0377          continue;
 378        }
 890379        string compileName = m.GetCompileName(Options);
 380        ModuleDefinition priorModDef;
 890381        if (compileNameMap.TryGetValue(compileName, out priorModDef)) {
 0382          reporter.Error(MessageSource.Resolver, m.tok,
 0383            "modules '{0}' and '{1}' both have CompileName '{2}'",
 0384            priorModDef.tok.val, m.tok.val, compileName);
 890385        } else {
 890386          compileNameMap.Add(compileName, m);
 890387        }
 890388      }
 445389    }
 390
 445391    public void ResolveProgram(Program prog) {
 392      Contract.Requires(prog != null);
 445393      Type.ResetScopes();
 394
 445395      Type.EnableScopes();
 396      // For the formatter, we ensure we take snapshots of the PrefixNamedModules
 397      // and topleveldecls
 445398      prog.DefaultModuleDef.PreResolveSnapshotForFormatter();
 445399      var origErrorCount = reporter.ErrorCount; //TODO: This is used further below, but not in the >0 comparisons in the
 445400      var bindings = new ModuleBindings(null);
 445401      var b = BindModuleNames(prog.DefaultModuleDef, bindings);
 445402      bindings.BindName(prog.DefaultModule.Name, prog.DefaultModule, b);
 445403      if (reporter.ErrorCount > 0) {
 0404        return;
 405      } // if there were errors, then the implict ModuleBindings data structure invariant
 406
 407      // is violated, so Processing dependencies will not succeed.
 445408      ProcessDependencies(prog.DefaultModule, b, dependencies);
 409      // check for cycles in the import graph
 1335410      foreach (var cycle in dependencies.AllCycles()) {
 0411        ReportCycleError(cycle, m => m.tok,
 0412          m => (m is AliasModuleDecl ? "import " : "module ") + m.Name,
 0413          "module definition contains a cycle (note: parent modules implicitly depend on submodules)");
 0414      }
 415
 445416      if (reporter.ErrorCount > 0) {
 0417        return;
 418      } // give up on trying to resolve anything else
 419
 420      // fill in module heights
 445421      List<ModuleDecl> sortedDecls = dependencies.TopologicallySortedComponents();
 445422      int h = 0;
 2670423      foreach (ModuleDecl md in sortedDecls) {
 445424        md.Height = h;
 890425        if (md is LiteralModuleDecl) {
 445426          var mdef = ((LiteralModuleDecl)md).ModuleDef;
 445427          mdef.Height = h;
 445428          prog.ModuleSigs.Add(mdef, null);
 445429        }
 445430        h++;
 445431      }
 432
 445433      rewriters = new List<IRewriter>();
 434
 445435      if (Options.AuditProgram) {
 0436        rewriters.Add(new Auditor.Auditor(reporter));
 0437      }
 438
 445439      refinementTransformer = new RefinementTransformer(prog);
 445440      rewriters.Add(refinementTransformer);
 890441      if (!Options.VerifyAllModules) {
 445442        rewriters.Add(new IncludedLemmaBodyRemover(prog, reporter));
 445443      }
 445444      rewriters.Add(new AutoContractsRewriter(reporter, builtIns));
 445445      rewriters.Add(new OpaqueMemberRewriter(this.reporter));
 445446      rewriters.Add(new AutoReqFunctionRewriter(this.reporter, this.builtIns));
 445447      rewriters.Add(new TimeLimitRewriter(reporter));
 445448      rewriters.Add(new ForallStmtRewriter(reporter));
 445449      rewriters.Add(new ProvideRevealAllRewriter(this.reporter));
 445450      rewriters.Add(new MatchFlattener(this.reporter, defaultTempVarIdGenerator));
 451
 890452      if (Options.AutoTriggers) {
 445453        rewriters.Add(new QuantifierSplittingRewriter(reporter));
 445454        rewriters.Add(new TriggerGeneratingRewriter(reporter));
 445455      }
 456
 445457      if (Options.TestContracts != DafnyOptions.ContractTestingMode.None) {
 0458        rewriters.Add(new ExpectContracts(reporter));
 0459      }
 460
 445461      if (Options.RunAllTests) {
 0462        rewriters.Add(new RunAllTestsMainMethod(reporter));
 0463      }
 464
 445465      rewriters.Add(new InductionRewriter(reporter));
 445466      rewriters.Add(new PrintEffectEnforcement(reporter));
 445467      rewriters.Add(new BitvectorOptimization(reporter));
 468
 445469      if (Options.DisallowConstructorCaseWithoutParentheses) {
 0470        rewriters.Add(new ConstructorWarning(reporter));
 0471      }
 445472      rewriters.Add(new LocalLinter(reporter));
 445473      rewriters.Add(new PrecedenceLinter(reporter));
 474
 4005475      foreach (var plugin in Options.Plugins) {
 890476        rewriters.AddRange(plugin.GetRewriters(reporter));
 890477      }
 478
 445479      systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule, false);
 445480      prog.CompileModules.Add(prog.BuiltIns.SystemModule);
 445481      RevealAllInScope(prog.BuiltIns.SystemModule.TopLevelDecls, systemNameInfo.VisibilityScope);
 445482      ResolveValuetypeDecls();
 483      // The SystemModule is constructed with all its members already being resolved. Except for
 484      // the non-null type corresponding to class types.  They are resolved here:
 445485      var systemModuleClassesWithNonNullTypes =
 14220486        prog.BuiltIns.SystemModule.TopLevelDecls.Where(d => (d as ClassDecl)?.NonNullTypeDecl != null).ToList();
 4005487      foreach (var cl in systemModuleClassesWithNonNullTypes) {
 890488        var d = ((ClassDecl)cl).NonNullTypeDecl;
 890489        allTypeParameters.PushMarker();
 890490        ResolveTypeParameters(d.TypeArgs, true, d);
 890491        ResolveType(d.tok, d.Rhs, d, ResolveTypeOptionEnum.AllowPrefix, d.TypeArgs);
 890492        allTypeParameters.PopMarker();
 890493      }
 445494      ResolveTopLevelDecls_Core(ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(systemModuleClassesWithNonNullTypes)
 445495        new Graph<IndDatatypeDecl>(), new Graph<CoDatatypeDecl>(), prog.BuiltIns.SystemModule.Name);
 496
 22695497      foreach (var rewriter in rewriters) {
 7120498        rewriter.PreResolve(prog);
 7120499      }
 500
 445501      var compilationModuleClones = new Dictionary<ModuleDefinition, ModuleDefinition>();
 2670502      foreach (var decl in sortedDecls) {
 890503        if (decl is LiteralModuleDecl) {
 504          // The declaration is a literal module, so it has members and such that we need
 505          // to resolve. First we do refinement transformation. Then we construct the signature
 506          // of the module. This is the public, externally visible signature. Then we add in
 507          // everything that the system defines, as well as any "import" (i.e. "opened" modules)
 508          // directives (currently not supported, but this is where we would do it.) This signature,
 509          // which is only used while resolving the members of the module is stored in the (basically)
 510          // global variable moduleInfo. Then the signatures of the module members are resolved, followed
 511          // by the bodies.
 445512          var literalDecl = (LiteralModuleDecl)decl;
 445513          var m = literalDecl.ModuleDef;
 514
 445515          var errorCount = reporter.ErrorCount;
 445516          if (m.RefinementQId != null) {
 0517            ModuleDecl md = ResolveModuleQualifiedId(m.RefinementQId.Root, m.RefinementQId, reporter);
 0518            m.RefinementQId.Set(md); // If module is not found, md is null and an error message has been emitted
 0519          }
 520
 22695521          foreach (var rewriter in rewriters) {
 7120522            rewriter.PreResolve(m);
 7120523          }
 524
 445525          literalDecl.Signature = RegisterTopLevelDecls(m, true);
 445526          literalDecl.Signature.Refines = refinementTransformer.RefinedSig;
 527
 445528          var sig = literalDecl.Signature;
 529          // set up environment
 445530          var preResolveErrorCount = reporter.ErrorCount;
 531
 445532          ResolveModuleExport(literalDecl, sig);
 445533          var good = ResolveModuleDefinition(m, sig);
 534
 890535          if (good && reporter.ErrorCount == preResolveErrorCount) {
 536            // Check that the module export gives a self-contained view of the module.
 445537            CheckModuleExportConsistency(m);
 445538          }
 539
 445540          var tempVis = new VisibilityScope();
 445541          tempVis.Augment(sig.VisibilityScope);
 445542          tempVis.Augment(systemNameInfo.VisibilityScope);
 445543          Type.PushScope(tempVis);
 544
 445545          prog.ModuleSigs[m] = sig;
 546
 22695547          foreach (var rewriter in rewriters) {
 7120548            if (!good || reporter.ErrorCount != preResolveErrorCount) {
 0549              break;
 550            }
 7120551            rewriter.PostResolveIntermediate(m);
 7120552          }
 890553          if (good && reporter.ErrorCount == errorCount) {
 445554            m.SuccessfullyResolved = true;
 445555          }
 445556          Type.PopScope(tempVis);
 557
 890558          if (reporter.ErrorCount == errorCount && !m.IsAbstract) {
 559            // compilation should only proceed if everything is good, including the signature (which preResolveErrorCoun
 445560            CompilationCloner cloner = new CompilationCloner(compilationModuleClones);
 445561            var nw = cloner.CloneModuleDefinition(m, new Name(m.NameNode.RangeToken, m.GetCompileName(Options) + "_Compi
 445562            compilationModuleClones.Add(m, nw);
 445563            var oldErrorsOnly = reporter.ErrorsOnly;
 445564            reporter.ErrorsOnly = true; // turn off warning reporting for the clone
 565            // Next, compute the compile signature
 445566            Contract.Assert(!useCompileSignatures);
 445567            useCompileSignatures = true; // set Resolver-global flag to indicate that Signatures should be followed to t
 445568            Type.DisableScopes();
 445569            var compileSig = RegisterTopLevelDecls(nw, true);
 445570            compileSig.Refines = refinementTransformer.RefinedSig;
 445571            sig.CompileSignature = compileSig;
 1335572            foreach (var exportDecl in sig.ExportSets.Values) {
 0573              exportDecl.Signature.CompileSignature = cloner.CloneModuleSignature(exportDecl.Signature, compileSig);
 0574            }
 575            // Now we're ready to resolve the cloned module definition, using the compile signature
 576
 445577            ResolveModuleDefinition(nw, compileSig);
 578
 22695579            foreach (var rewriter in rewriters) {
 7120580              rewriter.PostCompileCloneAndResolve(nw);
 7120581            }
 582
 445583            prog.CompileModules.Add(nw);
 445584            useCompileSignatures = false; // reset the flag
 445585            Type.EnableScopes();
 445586            reporter.ErrorsOnly = oldErrorsOnly;
 445587          }
 445588        } else if (decl is AliasModuleDecl alias) {
 589          // resolve the path
 590          ModuleSignature p;
 0591          if (ResolveExport(alias, alias.EnclosingModuleDefinition, alias.TargetQId, alias.Exports, out p, reporter)) {
 0592            if (alias.Signature == null) {
 0593              alias.Signature = p;
 0594            }
 0595          } else {
 0596            alias.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0597          }
 0598        } else if (decl is AbstractModuleDecl abs) {
 599          ModuleSignature p;
 0600          if (ResolveExport(abs, abs.EnclosingModuleDefinition, abs.QId, abs.Exports, out p, reporter)) {
 0601            abs.OriginalSignature = p;
 0602            abs.Signature = MakeAbstractSignature(p, abs.FullSanitizedName, abs.Height, prog.ModuleSigs, compilationModu
 0603          } else {
 0604            abs.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0605          }
 0606        } else if (decl is ModuleExportDecl) {
 0607          ((ModuleExportDecl)decl).SetupDefaultSignature();
 608
 0609          Contract.Assert(decl.Signature != null);
 0610          Contract.Assert(decl.Signature.VisibilityScope != null);
 611
 0612        } else {
 0613          Contract.Assert(false); // Unknown kind of ModuleDecl
 0614        }
 615
 445616        Contract.Assert(decl.Signature != null);
 445617      }
 618
 445619      if (reporter.ErrorCount != origErrorCount) {
 620        // do nothing else
 0621        return;
 622      }
 623
 624      // compute IsRecursive bit for mutually recursive functions and methods
 2670625      foreach (var module in prog.Modules()) {
 29610626        foreach (var clbl in ModuleDefinition.AllCallables(module.TopLevelDecls)) {
 16280627          if (clbl is Function) {
 6855628            var fn = (Function)clbl;
 13710629            if (!fn.IsRecursive) { // note, self-recursion has already been determined
 6855630              int n = module.CallGraph.GetSCCSize(fn);
 6855631              if (2 <= n) {
 632                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0633                fn.IsRecursive = true;
 0634              }
 6855635            }
 6855636            if (fn.IsRecursive && fn is ExtremePredicate) {
 637              // this means the corresponding prefix predicate is also recursive
 0638              var prefixPred = ((ExtremePredicate)fn).PrefixPredicate;
 0639              if (prefixPred != null) {
 0640                prefixPred.IsRecursive = true;
 0641              }
 0642            }
 9425643          } else {
 2570644            var m = (Method)clbl;
 5140645            if (!m.IsRecursive) {
 646              // note, self-recursion has already been determined
 2570647              int n = module.CallGraph.GetSCCSize(m);
 2570648              if (2 <= n) {
 649                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0650              }
 2570651            }
 2570652          }
 9425653        }
 654
 22695655        foreach (var rewriter in rewriters) {
 7120656          rewriter.PostCyclicityResolve(module);
 7120657        }
 445658      }
 659
 660      // fill in default decreases clauses:  for functions and methods, and for loops
 445661      new InferDecreasesClause(this).FillInDefaultDecreasesClauses(prog);
 2670662      foreach (var module in prog.Modules()) {
 29610663        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 9425664          Statement body = null;
 11995665          if (clbl is Method) {
 2570666            body = ((Method)clbl).Body;
 9425667          } else if (clbl is IteratorDecl) {
 0668            body = ((IteratorDecl)clbl).Body;
 0669          }
 670
 11995671          if (body != null) {
 2570672            var c = new FillInDefaultLoopDecreases_Visitor(this, clbl);
 2570673            c.Visit(body);
 2570674          }
 9425675        }
 445676      }
 677
 2670678      foreach (var module in prog.Modules()) {
 1335679        foreach (var iter in ModuleDefinition.AllIteratorDecls(module.TopLevelDecls)) {
 0680          reporter.Info(MessageSource.Resolver, iter.tok, Printer.IteratorClassToString(Reporter.Options, iter));
 0681        }
 445682      }
 683
 2670684      foreach (var module in prog.Modules()) {
 22695685        foreach (var rewriter in rewriters) {
 7120686          rewriter.PostDecreasesResolve(module);
 7120687        }
 445688      }
 689
 690      // fill in other additional information
 2670691      foreach (var module in prog.Modules()) {
 29610692        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 9425693          Statement body = null;
 9425694          if (clbl is ExtremeLemma) {
 0695            body = ((ExtremeLemma)clbl).PrefixLemma.Body;
 11995696          } else if (clbl is Method) {
 2570697            body = ((Method)clbl).Body;
 9425698          } else if (clbl is IteratorDecl) {
 0699            body = ((IteratorDecl)clbl).Body;
 0700          }
 701
 11995702          if (body != null) {
 2570703            var c = new ReportOtherAdditionalInformation_Visitor(this);
 2570704            c.Visit(body);
 2570705          }
 9425706        }
 445707      }
 708
 709      // Determine, for each function, whether someone tries to adjust its fuel parameter
 2670710      foreach (var module in prog.Modules()) {
 445711        CheckForFuelAdjustments(module.tok, module.Attributes, module);
 29610712        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 9425713          Statement body = null;
 11995714          if (clbl is Method) {
 2570715            body = ((Method)clbl).Body;
 2570716            CheckForFuelAdjustments(clbl.Tok, ((Method)clbl).Attributes, module);
 9425717          } else if (clbl is IteratorDecl) {
 0718            body = ((IteratorDecl)clbl).Body;
 0719            CheckForFuelAdjustments(clbl.Tok, ((IteratorDecl)clbl).Attributes, module);
 13710720          } else if (clbl is Function) {
 6855721            CheckForFuelAdjustments(clbl.Tok, ((Function)clbl).Attributes, module);
 6855722            var c = new FuelAdjustment_Visitor(this);
 6855723            var bodyExpr = ((Function)clbl).Body;
 13710724            if (bodyExpr != null) {
 6855725              c.Visit(bodyExpr, new FuelAdjustment_Context(module));
 6855726            }
 6855727          }
 728
 11995729          if (body != null) {
 2570730            var c = new FuelAdjustment_Visitor(this);
 2570731            c.Visit(body, new FuelAdjustment_Context(module));
 2570732          }
 9425733        }
 445734      }
 735
 445736      Type.DisableScopes();
 445737      CheckDupModuleNames(prog);
 738
 2670739      foreach (var module in prog.Modules()) {
 22695740        foreach (var rewriter in rewriters) {
 7120741          rewriter.PostResolve(module);
 7120742        }
 445743      }
 744
 22695745      foreach (var rewriter in rewriters) {
 7120746        rewriter.PostResolve(prog);
 7120747      }
 445748    }
 749
 750
 751
 445752    private void ResolveValuetypeDecls() {
 445753      moduleInfo = systemNameInfo;
 10680754      foreach (var valueTypeDecl in valuetypeDecls) {
 26700755        foreach (var kv in valueTypeDecl.Members) {
 6675756          if (kv.Value is Function function) {
 890757            ResolveFunctionSignature(function);
 890758            CallGraphBuilder.VisitFunction(function, reporter);
 5785759          } else if (kv.Value is Method method) {
 0760            ResolveMethodSignature(method);
 0761            CallGraphBuilder.VisitMethod(method, reporter);
 0762          }
 5785763        }
 3115764      }
 445765    }
 766
 767    /// <summary>
 768    /// Resolves the module definition.
 769    /// A return code of "false" is an indication of an error that may or may not have
 770    /// been reported in an error message. So, in order to figure out if m was successfully
 771    /// resolved, a caller has to check for both a change in error count and a "false"
 772    /// return value.
 773    /// </summary>
 890774    private bool ResolveModuleDefinition(ModuleDefinition m, ModuleSignature sig, bool isAnExport = false) {
 775      Contract.Requires(AllTypeConstraints.Count == 0);
 776      Contract.Ensures(AllTypeConstraints.Count == 0);
 777
 890778      sig.VisibilityScope.Augment(systemNameInfo.VisibilityScope);
 779      // make sure all imported modules were successfully resolved
 5340780      foreach (var d in m.TopLevelDecls) {
 890781        if (d is AliasModuleDecl || d is AbstractModuleDecl) {
 782          ModuleSignature importSig;
 0783          if (d is AliasModuleDecl) {
 0784            var alias = (AliasModuleDecl)d;
 0785            importSig = alias.TargetQId.Root != null ? alias.TargetQId.Root.Signature : alias.Signature;
 0786          } else {
 0787            importSig = ((AbstractModuleDecl)d).OriginalSignature;
 0788          }
 789
 0790          if (importSig.ModuleDef == null || !importSig.ModuleDef.SuccessfullyResolved) {
 0791            if (!m.IsEssentiallyEmptyModuleBody()) {
 792              // say something only if this will cause any testing to be omitted
 0793              reporter.Error(MessageSource.Resolver, d,
 0794                "not resolving module '{0}' because there were errors in resolving its import '{1}'", m.Name, d.Name);
 0795            }
 796
 0797            return false;
 798          }
 890799        } else if (d is LiteralModuleDecl) {
 0800          var nested = (LiteralModuleDecl)d;
 0801          if (!nested.ModuleDef.SuccessfullyResolved) {
 0802            if (!m.IsEssentiallyEmptyModuleBody()) {
 803              // say something only if this will cause any testing to be omitted
 0804              reporter.Error(MessageSource.Resolver, nested,
 0805                "not resolving module '{0}' because there were errors in resolving its nested module '{1}'", m.Name,
 0806                nested.Name);
 0807            }
 808
 0809            return false;
 810          }
 0811        }
 890812      }
 813
 814      // resolve
 890815      var oldModuleInfo = moduleInfo;
 890816      moduleInfo = MergeSignature(sig, systemNameInfo);
 890817      Type.PushScope(moduleInfo.VisibilityScope);
 890818      ResolveOpenedImports(moduleInfo, m, useCompileSignatures, this); // opened imports do not persist
 890819      var datatypeDependencies = new Graph<IndDatatypeDecl>();
 890820      var codatatypeDependencies = new Graph<CoDatatypeDecl>();
 890821      var allDeclarations = ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(m.TopLevelDecls).ToList();
 890822      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 890823      ResolveTopLevelDecls_Signatures(m, sig, allDeclarations, datatypeDependencies, codatatypeDependencies);
 890824      Contract.Assert(AllTypeConstraints.Count == 0); // signature resolution does not add any type constraints
 825
 890826      scope.PushMarker();
 890827      scope.AllowInstance = false;
 890828      ResolveAttributes(m, new ResolutionContext(new NoContext(m.EnclosingModule), false), true); // Must follow Resolve
 890829      scope.PopMarker();
 830
 1780831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 890832        ResolveTopLevelDecls_Core(allDeclarations, datatypeDependencies, codatatypeDependencies, m.Name, isAnExport);
 890833      }
 834
 890835      Type.PopScope(moduleInfo.VisibilityScope);
 890836      moduleInfo = oldModuleInfo;
 890837      return true;
 890838    }
 839
 840    // Resolve the exports and detect cycles.
 445841    private void ResolveModuleExport(LiteralModuleDecl literalDecl, ModuleSignature sig) {
 445842      ModuleDefinition m = literalDecl.ModuleDef;
 445843      literalDecl.DefaultExport = sig;
 445844      Graph<ModuleExportDecl> exportDependencies = new Graph<ModuleExportDecl>();
 2670845      foreach (TopLevelDecl toplevel in m.TopLevelDecls) {
 445846        if (toplevel is ModuleExportDecl) {
 0847          ModuleExportDecl d = (ModuleExportDecl)toplevel;
 0848          exportDependencies.AddVertex(d);
 0849          foreach (IToken s in d.Extends) {
 850            ModuleExportDecl extend;
 0851            if (sig.ExportSets.TryGetValue(s.val, out extend)) {
 0852              d.ExtendDecls.Add(extend);
 0853              exportDependencies.AddEdge(d, extend);
 0854            } else {
 0855              reporter.Error(MessageSource.Resolver, s, s.val + " must be an export of " + m.Name + " to be extended");
 0856            }
 0857          }
 0858        }
 445859      }
 860
 861      // detect cycles in the extend
 445862      var cycleError = false;
 1335863      foreach (var cycle in exportDependencies.AllCycles()) {
 0864        ReportCycleError(cycle, m => m.tok, m => m.Name, "module export contains a cycle");
 0865        cycleError = true;
 0866      }
 867
 445868      if (cycleError) {
 0869        return;
 870      } // give up on trying to resolve anything else
 871
 872      // fill in the exports for the extends.
 445873      List<ModuleExportDecl> sortedExportDecls = exportDependencies.TopologicallySortedComponents();
 445874      ModuleExportDecl defaultExport = null;
 875      TopLevelDecl defaultClass;
 876
 445877      sig.TopLevels.TryGetValue("_default", out defaultClass);
 445878      Contract.Assert(defaultClass is ClassDecl);
 445879      Contract.Assert(((ClassDecl)defaultClass).IsDefaultClass);
 445880      defaultClass.AddVisibilityScope(m.VisibilityScope, true);
 881
 1335882      foreach (var d in sortedExportDecls) {
 883
 0884        defaultClass.AddVisibilityScope(d.ThisScope, true);
 885
 0886        foreach (var eexports in d.ExtendDecls.Select(e => e.Exports)) {
 0887          d.Exports.AddRange(eexports);
 0888        }
 889
 0890        if (d.ExtendDecls.Count == 0 && d.Exports.Count == 0) {
 891          // This is an empty export.  This is allowed, but unusual.  It could pop up, for example, if
 892          // someone temporary comments out everything that the export set provides/reveals.  However,
 893          // if the name of the export set coincides with something else that's declared at the top
 894          // level of the module, then this export declaration is more likely an error--the user probably
 895          // forgot the "provides" or "reveals" keyword.
 896          Dictionary<string, MemberDecl> members;
 897          MemberDecl member;
 898          // Top-level functions and methods are actually recorded as members of the _default class.  We look up the
 899          // export-set name there.  If the export-set name happens to coincide with some other top-level declaration,
 900          // then an error will already have been produced ("duplicate name of top-level declaration").
 0901          if (classMembers.TryGetValue((ClassDecl)defaultClass, out members) &&
 0902              members.TryGetValue(d.Name, out member)) {
 0903            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, d.tok,
 0904              "note, this export set is empty (did you perhaps forget the 'provides' or 'reveals' keyword?)");
 0905          }
 0906        }
 907
 0908        foreach (ExportSignature export in d.Exports) {
 909
 910          // check to see if it is a datatype or a member or
 911          // static function or method in the enclosing module or its imports
 912          TopLevelDecl tdecl;
 913          MemberDecl member;
 914          TopLevelDecl cldecl;
 915
 0916          Declaration decl = null;
 0917          string name = export.Id;
 918
 0919          if (export.ClassId != null) {
 0920            if (!sig.TopLevels.TryGetValue(export.ClassId, out cldecl)) {
 0921              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a top-level type declaration",
 0922                export.ClassId);
 0923              continue;
 924            }
 925
 0926            if (cldecl is ClassDecl && ((ClassDecl)cldecl).NonNullTypeDecl != null) {
 927              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0928              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0929                export.ClassId);
 0930              continue;
 931            }
 932
 0933            if (cldecl is NonNullTypeDecl) {
 934              // cldecl was given syntactically like the name of a class, but here it's referring to the corresponding n
 0935              cldecl = cldecl.ViewAsClass;
 0936            }
 937
 0938            var mt = cldecl as TopLevelDeclWithMembers;
 0939            if (mt == null) {
 0940              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0941                export.ClassId);
 0942              continue;
 943            }
 944
 0945            var lmem = mt.Members.FirstOrDefault(l => l.Name == export.Id);
 0946            if (lmem == null) {
 0947              reporter.Error(MessageSource.Resolver, export.Tok, "No member '{0}' found in type '{1}'", export.Id,
 0948                export.ClassId);
 0949              continue;
 950            }
 951
 0952            decl = lmem;
 0953          } else if (sig.TopLevels.TryGetValue(name, out tdecl)) {
 0954            if (tdecl is ClassDecl && ((ClassDecl)tdecl).NonNullTypeDecl != null) {
 955              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0956              var nn = ((ClassDecl)tdecl).NonNullTypeDecl;
 0957              Contract.Assert(nn != null);
 0958              reporter.Error(MessageSource.Resolver, export.Tok,
 0959                export.Opaque
 0960                  ? "Type '{1}' can only be revealed, not provided"
 0961                  : "Types '{0}' and '{1}' are exported together, which is accomplished by revealing the name '{0}'",
 0962                nn.Name, name);
 0963              continue;
 964            }
 965
 966            // Member of the enclosing module
 0967            decl = tdecl;
 0968          } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 0969            decl = member;
 0970          } else if (sig.ExportSets.ContainsKey(name)) {
 0971            reporter.Error(MessageSource.Resolver, export.Tok,
 0972              "'{0}' is an export set and cannot be provided/revealed by another export set (did you intend to list it i
 0973              name);
 0974            continue;
 0975          } else {
 0976            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' must be a member of '{1}' to be exported", name,
 0977              m.Name);
 0978            continue;
 979          }
 980
 0981          if (!decl.CanBeExported()) {
 0982            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' is not a valid export of '{1}'", name, m.Name);
 0983            continue;
 984          }
 985
 0986          if (!export.Opaque && !decl.CanBeRevealed()) {
 0987            reporter.Error(MessageSource.Resolver, export.Tok,
 0988              "'{0}' cannot be revealed in an export. Use \"provides\" instead.", name);
 0989            continue;
 990          }
 991
 0992          export.Decl = decl;
 0993          if (decl is NonNullTypeDecl nntd) {
 0994            nntd.AddVisibilityScope(d.ThisScope, export.Opaque);
 0995            if (!export.Opaque) {
 0996              nntd.Class.AddVisibilityScope(d.ThisScope, export.Opaque);
 997              // add the anonymous constructor, if any
 0998              var anonymousConstructor = nntd.Class.Members.Find(mdecl => mdecl.Name == "_ctor");
 0999              if (anonymousConstructor != null) {
 01000                anonymousConstructor.AddVisibilityScope(d.ThisScope, false);
 01001              }
 01002            }
 01003          } else {
 01004            decl.AddVisibilityScope(d.ThisScope, export.Opaque);
 01005          }
 01006        }
 01007      }
 1008
 13351009      foreach (ModuleExportDecl decl in sortedExportDecls) {
 01010        if (decl.IsDefault) {
 01011          if (defaultExport == null) {
 01012            defaultExport = decl;
 01013          } else {
 01014            reporter.Error(MessageSource.Resolver, m.tok, "more than one default export set declared in module {0}",
 01015              m.Name);
 01016          }
 01017        }
 1018
 1019        // fill in export signature
 01020        ModuleSignature signature = decl.Signature;
 01021        if (signature != null) {
 01022          signature.ModuleDef = m;
 01023        }
 1024
 01025        foreach (var top in sig.TopLevels) {
 01026          if (!top.Value.CanBeExported() || !top.Value.IsVisibleInScope(signature.VisibilityScope)) {
 01027            continue;
 1028          }
 1029
 01030          if (!signature.TopLevels.ContainsKey(top.Key)) {
 01031            signature.TopLevels.Add(top.Key, top.Value);
 01032          }
 1033
 01034          if (top.Value is DatatypeDecl && top.Value.IsRevealedInScope(signature.VisibilityScope)) {
 01035            foreach (var ctor in ((DatatypeDecl)top.Value).Ctors) {
 01036              if (!signature.Ctors.ContainsKey(ctor.Name)) {
 01037                signature.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 01038              }
 01039            }
 01040          }
 01041        }
 1042
 01043        foreach (var mem in sig.StaticMembers.Where(t =>
 01044          t.Value.IsVisibleInScope(signature.VisibilityScope) && t.Value.CanBeExported())) {
 01045          if (!signature.StaticMembers.ContainsKey(mem.Key)) {
 01046            signature.StaticMembers.Add(mem.Key, (MemberDecl)mem.Value);
 01047          }
 01048        }
 01049      }
 1050
 1051      // set the default export set, if it exists
 4451052      if (defaultExport != null) {
 01053        literalDecl.DefaultExport = defaultExport.Signature;
 4451054      } else if (sortedExportDecls.Count > 0) {
 01055        literalDecl.DefaultExport = null;
 01056      }
 1057
 1058      // final pass to propagate visibility of exported imports
 4451059      var sigs = sortedExportDecls.Select(d => d.Signature).Concat1(sig);
 1060
 26701061      foreach (var s in sigs) {
 26701062        foreach (var decl in s.TopLevels) {
 4451063          if (decl.Value is ModuleDecl && !(decl.Value is ModuleExportDecl)) {
 01064            var modDecl = (ModuleDecl)decl.Value;
 01065            s.VisibilityScope.Augment(modDecl.AccessibleSignature().VisibilityScope);
 01066          }
 4451067        }
 4451068      }
 1069
 4451070      var exported = new HashSet<Tuple<Declaration, bool>>();
 1071
 1072      //some decls may not be set due to resolution errors
 13351073      foreach (var e in sortedExportDecls.SelectMany(e => e.Exports).Where(e => e.Decl != null)) {
 01074        var decl = e.Decl;
 01075        exported.Add(new Tuple<Declaration, bool>(decl, e.Opaque));
 01076        if (!e.Opaque && decl.CanBeRevealed()) {
 01077          exported.Add(new Tuple<Declaration, bool>(decl, true));
 01078          if (decl is NonNullTypeDecl nntd) {
 01079            exported.Add(new Tuple<Declaration, bool>(nntd.Class, true));
 01080          }
 01081        }
 1082
 01083        if (e.Opaque && (decl is DatatypeDecl || decl is TypeSynonymDecl)) {
 1084          // Datatypes and type synonyms are marked as _provided when they appear in any provided export.  If a
 1085          // declaration is never provided, then either it isn't visible outside the module at all or its whole
 1086          // definition is.  Datatype and type-synonym declarations undergo some inference from their definitions.
 1087          // Such inference should not be done for provided declarations, since different views of the module
 1088          // would then get different inferred properties.
 01089          decl.Attributes = new Attributes("_provided", new List<Expression>(), decl.Attributes);
 01090          reporter.Info(MessageSource.Resolver, decl.tok, "{:_provided}");
 01091        }
 01092      }
 1093
 4451094      Dictionary<RevealableTypeDecl, bool?> declScopes = new Dictionary<RevealableTypeDecl, bool?>();
 4451095      Dictionary<RevealableTypeDecl, bool?> modifies = new Dictionary<RevealableTypeDecl, bool?>();
 1096
 1097      //of all existing types, compute the minimum visibility of them for each exported declaration's
 1098      //body and signature
 13351099      foreach (var e in exported) {
 1100
 01101        declScopes.Clear();
 01102        modifies.Clear();
 1103
 01104        foreach (var typ in revealableTypes) {
 01105          declScopes.Add(typ, null);
 01106        }
 1107
 01108        foreach (var decl in sortedExportDecls) {
 01109          if (decl.Exports.Exists(ex => ex.Decl == e.Item1 && (e.Item2 || !ex.Opaque))) {
 1110            //if we are revealed, consider those exports where we are provided as well
 01111            var scope = decl.Signature.VisibilityScope;
 1112
 01113            foreach (var kv in declScopes) {
 01114              bool? isOpaque = kv.Value;
 01115              var typ = kv.Key;
 01116              if (!typ.AsTopLevelDecl.IsVisibleInScope(scope)) {
 01117                modifies[typ] = null;
 01118                continue;
 1119              }
 1120
 01121              if (isOpaque.HasValue && isOpaque.Value) {
 1122                //type is visible here, but known-opaque, so do nothing
 01123                continue;
 1124              }
 1125
 01126              modifies[typ] = !typ.AsTopLevelDecl.IsRevealedInScope(scope);
 01127            }
 1128
 01129            foreach (var kv in modifies) {
 01130              if (!kv.Value.HasValue) {
 01131                declScopes.Remove(kv.Key);
 01132              } else {
 01133                var exvis = declScopes[kv.Key];
 01134                if (exvis.HasValue) {
 01135                  declScopes[kv.Key] = exvis.Value || kv.Value.Value;
 01136                } else {
 01137                  declScopes[kv.Key] = kv.Value;
 01138                }
 01139              }
 01140            }
 1141
 01142            modifies.Clear();
 01143          }
 01144        }
 1145
 01146        VisibilityScope newscope = new VisibilityScope(e.Item1.Name);
 1147
 01148        foreach (var rt in declScopes) {
 01149          if (!rt.Value.HasValue) {
 01150            continue;
 1151          }
 1152
 01153          rt.Key.AsTopLevelDecl.AddVisibilityScope(newscope, rt.Value.Value);
 01154        }
 01155      }
 4451156    }
 1157
 1158    //check for export consistency by resolving internal modules
 1159    //this should be effect-free, as it only operates on clones
 4451160    private void CheckModuleExportConsistency(ModuleDefinition m) {
 4451161      var oldModuleInfo = moduleInfo;
 13351162      foreach (var exportDecl in m.TopLevelDecls.OfType<ModuleExportDecl>()) {
 1163
 01164        var prevErrors = reporter.Count(ErrorLevel.Error);
 1165
 01166        foreach (var export in exportDecl.Exports) {
 01167          if (export.Decl is MemberDecl member) {
 1168            // For classes and traits, the visibility test is performed on the corresponding non-null type
 01169            var enclosingType = member.EnclosingClass is ClassDecl cl && cl.NonNullTypeDecl != null
 01170              ? cl.NonNullTypeDecl
 01171              : member.EnclosingClass;
 01172            if (!enclosingType.IsVisibleInScope(exportDecl.Signature.VisibilityScope)) {
 01173              reporter.Error(MessageSource.Resolver, export.Tok,
 01174                "Cannot export type member '{0}' without providing its enclosing {1} '{2}'", member.Name,
 01175                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01176            } else if (member is Constructor &&
 01177                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01178              reporter.Error(MessageSource.Resolver, export.Tok,
 01179                "Cannot export constructor '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01180                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01181            } else if (member is Field && !(member is ConstantField) &&
 01182                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01183              reporter.Error(MessageSource.Resolver, export.Tok,
 01184                "Cannot export mutable field '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01185                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01186            }
 01187          }
 01188        }
 1189
 01190        var scope = exportDecl.Signature.VisibilityScope;
 01191        Cloner cloner = new ScopeCloner(scope);
 01192        var exportView = cloner.CloneModuleDefinition(m, m.NameNode);
 01193        if (Options.DafnyPrintExportedViews.Contains(exportDecl.FullName)) {
 01194          var wr = Options.OutputWriter;
 01195          wr.WriteLine("/* ===== export set {0}", exportDecl.FullName);
 01196          var pr = new Printer(wr, Options);
 01197          pr.PrintTopLevelDecls(exportView.TopLevelDecls, 0, null, null);
 01198          wr.WriteLine("*/");
 01199        }
 1200
 01201        if (reporter.Count(ErrorLevel.Error) != prevErrors) {
 01202          continue;
 1203        }
 1204
 01205        reporter = new ErrorReporterWrapper(reporter,
 01206          String.Format("Raised while checking export set {0}: ", exportDecl.Name));
 01207        var testSig = RegisterTopLevelDecls(exportView, true);
 1208        //testSig.Refines = refinementTransformer.RefinedSig;
 01209        ResolveModuleDefinition(exportView, testSig, true);
 01210        var wasError = reporter.Count(ErrorLevel.Error) > 0;
 01211        reporter = ((ErrorReporterWrapper)reporter).WrappedReporter;
 1212
 01213        if (wasError) {
 01214          reporter.Error(MessageSource.Resolver, exportDecl.tok, "This export set is not consistent: {0}", exportDecl.Na
 01215        }
 01216      }
 1217
 4451218      moduleInfo = oldModuleInfo;
 4451219    }
 1220
 1221    public class ModuleBindings {
 1222      private ModuleBindings parent;
 1223      private Dictionary<string, ModuleDecl> modules;
 1224      private Dictionary<string, ModuleBindings> bindings;
 1225
 17801226      public ModuleBindings(ModuleBindings p) {
 8901227        parent = p;
 8901228        modules = new Dictionary<string, ModuleDecl>();
 8901229        bindings = new Dictionary<string, ModuleBindings>();
 8901230      }
 1231
 4451232      public bool BindName(string name, ModuleDecl subModule, ModuleBindings b) {
 4451233        if (modules.ContainsKey(name)) {
 01234          return false;
 4451235        } else {
 4451236          modules.Add(name, subModule);
 4451237          bindings.Add(name, b);
 4451238          return true;
 1239        }
 4451240      }
 1241
 01242      public bool TryLookup(IToken name, out ModuleDecl m) {
 1243        Contract.Requires(name != null);
 01244        return TryLookupFilter(name, out m, l => true);
 01245      }
 1246
 01247      public bool TryLookupFilter(IToken name, out ModuleDecl m, Func<ModuleDecl, bool> filter) {
 1248        Contract.Requires(name != null);
 01249        if (modules.TryGetValue(name.val, out m) && filter(m)) {
 01250          return true;
 01251        } else if (parent != null) {
 01252          return parent.TryLookupFilter(name, out m, filter);
 01253        } else {
 01254          return false;
 1255        }
 01256      }
 1257
 1258      public IEnumerable<ModuleDecl> ModuleList {
 01259        get { return modules.Values; }
 1260      }
 1261
 01262      public ModuleBindings SubBindings(string name) {
 01263        ModuleBindings v = null;
 01264        bindings.TryGetValue(name, out v);
 01265        return v;
 01266      }
 1267    }
 1268
 4451269    private ModuleBindings BindModuleNames(ModuleDefinition moduleDecl, ModuleBindings parentBindings) {
 4451270      var bindings = new ModuleBindings(parentBindings);
 1271
 1272      // moduleDecl.PrefixNamedModules is a list of pairs like:
 1273      //     A.B.C  ,  module D { ... }
 1274      // We collect these according to the first component of the prefix, like so:
 1275      //     "A"   ->   (A.B.C  ,  module D { ... })
 4451276      var prefixNames = new Dictionary<string, List<Tuple<List<IToken>, LiteralModuleDecl>>>();
 13351277      foreach (var tup in moduleDecl.PrefixNamedModules) {
 01278        var id = tup.Item1[0].val;
 1279        List<Tuple<List<IToken>, LiteralModuleDecl>> prev;
 01280        if (!prefixNames.TryGetValue(id, out prev)) {
 01281          prev = new List<Tuple<List<IToken>, LiteralModuleDecl>>();
 01282        }
 1283
 01284        prev.Add(tup);
 01285        prefixNames[id] = prev;
 01286      }
 1287
 4451288      moduleDecl.PrefixNamedModules.Clear();
 1289
 1290      // First, register all literal modules, and transferring their prefix-named modules downwards
 26701291      foreach (var tld in moduleDecl.TopLevelDecls) {
 4451292        if (tld is LiteralModuleDecl) {
 01293          var subdecl = (LiteralModuleDecl)tld;
 1294          // Transfer prefix-named modules downwards into the sub-module
 1295          List<Tuple<List<IToken>, LiteralModuleDecl>> prefixModules;
 01296          if (prefixNames.TryGetValue(subdecl.Name, out prefixModules)) {
 01297            prefixNames.Remove(subdecl.Name);
 01298            prefixModules = prefixModules.ConvertAll(ShortenPrefix);
 01299          } else {
 01300            prefixModules = null;
 01301          }
 1302
 01303          BindModuleName_LiteralModuleDecl(subdecl, prefixModules, bindings);
 01304        }
 4451305      }
 1306
 1307      // Next, add new modules for any remaining entries in "prefixNames".
 13351308      foreach (var entry in prefixNames) {
 01309        var name = entry.Key;
 01310        var prefixNamedModules = entry.Value;
 01311        var tok = prefixNamedModules.First().Item1[0];
 01312        var modDef = new ModuleDefinition(tok.ToRange(), new Name(tok.ToRange(), name), new List<IToken>(), false, false
 01313          true, true);
 1314        // Every module is expected to have a default class, so we create and add one now
 01315        var defaultClass = new DefaultClassDecl(modDef, new List<MemberDecl>());
 01316        modDef.TopLevelDecls.Add(defaultClass);
 1317        // Add the new module to the top-level declarations of its parent and then bind its names as usual
 01318        var subdecl = new LiteralModuleDecl(modDef, moduleDecl);
 01319        moduleDecl.TopLevelDecls.Add(subdecl);
 01320        BindModuleName_LiteralModuleDecl(subdecl, prefixNamedModules.ConvertAll(ShortenPrefix), bindings);
 01321      }
 1322
 1323      // Finally, go through import declarations (that is, AbstractModuleDecl's and AliasModuleDecl's).
 26701324      foreach (var tld in moduleDecl.TopLevelDecls) {
 4451325        if (tld is AbstractModuleDecl || tld is AliasModuleDecl) {
 01326          var subdecl = (ModuleDecl)tld;
 01327          if (bindings.BindName(subdecl.Name, subdecl, null)) {
 1328            // the add was successful
 01329          } else {
 1330            // there's already something with this name
 1331            ModuleDecl prevDecl;
 01332            var yes = bindings.TryLookup(subdecl.tok, out prevDecl);
 01333            Contract.Assert(yes);
 01334            if (prevDecl is AbstractModuleDecl || prevDecl is AliasModuleDecl) {
 01335              reporter.Error(MessageSource.Resolver, subdecl.tok, "Duplicate name of import: {0}", subdecl.Name);
 01336            } else if (tld is AliasModuleDecl importDecl && importDecl.Opened && importDecl.TargetQId.Path.Count == 1 &&
 01337                       importDecl.Name == importDecl.TargetQId.rootName()) {
 01338              importDecl.ShadowsLiteralModule = true;
 01339            } else {
 01340              reporter.Error(MessageSource.Resolver, subdecl.tok,
 01341                "Import declaration uses same name as a module in the same scope: {0}", subdecl.Name);
 01342            }
 01343          }
 01344        }
 4451345      }
 1346
 4451347      return bindings;
 4451348    }
 1349
 01350    private Tuple<List<IToken>, LiteralModuleDecl> ShortenPrefix(Tuple<List<IToken>, LiteralModuleDecl> tup) {
 1351      Contract.Requires(tup.Item1.Count != 0);
 01352      var rest = tup.Item1.GetRange(1, tup.Item1.Count - 1);
 01353      return new Tuple<List<IToken>, LiteralModuleDecl>(rest, tup.Item2);
 01354    }
 1355
 1356    private void BindModuleName_LiteralModuleDecl(LiteralModuleDecl litmod,
 01357      List<Tuple<List<IToken>, LiteralModuleDecl>> /*?*/ prefixModules, ModuleBindings parentBindings) {
 1358      Contract.Requires(litmod != null);
 1359      Contract.Requires(parentBindings != null);
 1360
 1361      // Transfer prefix-named modules downwards into the sub-module
 01362      if (prefixModules != null) {
 01363        foreach (var tup in prefixModules) {
 01364          if (tup.Item1.Count == 0) {
 01365            tup.Item2.ModuleDef.EnclosingModule =
 01366              litmod.ModuleDef; // change the parent, now that we have found the right parent module for the prefix-name
 01367            var sm = new LiteralModuleDecl(tup.Item2.ModuleDef,
 01368              litmod.ModuleDef); // this will create a ModuleDecl with the right parent
 01369            litmod.ModuleDef.TopLevelDecls.Add(sm);
 01370          } else {
 01371            litmod.ModuleDef.PrefixNamedModules.Add(tup);
 01372          }
 01373        }
 01374      }
 1375
 01376      var bindings = BindModuleNames(litmod.ModuleDef, parentBindings);
 01377      if (!parentBindings.BindName(litmod.Name, litmod, bindings)) {
 01378        reporter.Error(MessageSource.Resolver, litmod.tok, "Duplicate module name: {0}", litmod.Name);
 01379      }
 01380    }
 1381
 1382    private bool ResolveQualifiedModuleIdRootRefines(ModuleDefinition context, ModuleBindings bindings, ModuleQualifiedI
 01383      out ModuleDecl result) {
 01384      Contract.Assert(qid != null);
 01385      IToken root = qid.Path[0].StartToken;
 01386      result = null;
 01387      bool res = bindings.TryLookupFilter(root, out result, m => m.EnclosingModuleDefinition != context);
 01388      qid.Root = result;
 01389      return res;
 01390    }
 1391
 1392    // Find a matching module for the root of the QualifiedId, ignoring
 1393    // (a) the module (context) itself and (b) any local imports
 1394    // The latter is so that if one writes 'import A`E  import F = A`F' the second A does not
 1395    // resolve to the alias produced by the first import
 1396    private bool ResolveQualifiedModuleIdRootImport(AliasModuleDecl context, ModuleBindings bindings, ModuleQualifiedId 
 01397      out ModuleDecl result) {
 01398      Contract.Assert(qid != null);
 01399      IToken root = qid.Path[0].StartToken;
 01400      result = null;
 01401      bool res = bindings.TryLookupFilter(root, out result,
 01402        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01403      qid.Root = result;
 01404      return res;
 01405    }
 1406
 1407    private bool ResolveQualifiedModuleIdRootAbstract(AbstractModuleDecl context, ModuleBindings bindings, ModuleQualifi
 01408      out ModuleDecl result) {
 01409      Contract.Assert(qid != null);
 01410      IToken root = qid.Path[0].StartToken;
 01411      result = null;
 01412      bool res = bindings.TryLookupFilter(root, out result,
 01413        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01414      qid.Root = result;
 01415      return res;
 01416    }
 1417
 1418    private void ProcessDependenciesDefinition(ModuleDecl decl, ModuleDefinition m, ModuleBindings bindings,
 4451419      Graph<ModuleDecl> dependencies) {
 4451420      Contract.Assert(decl is LiteralModuleDecl);
 4451421      if (m.RefinementQId != null) {
 1422        ModuleDecl other;
 01423        bool res = ResolveQualifiedModuleIdRootRefines(((LiteralModuleDecl)decl).ModuleDef, bindings, m.RefinementQId, o
 01424        if (!res) {
 01425          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(),
 01426            $"module {m.RefinementQId.ToString()} named as refinement base does not exist");
 01427        } else if (other is LiteralModuleDecl && ((LiteralModuleDecl)other).ModuleDef == m) {
 01428          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(), "module cannot refine itself: {0}",
 01429            m.RefinementQId.ToString());
 01430        } else {
 01431          Contract.Assert(other != null); // follows from postcondition of TryGetValue
 01432          dependencies.AddEdge(decl, other);
 01433        }
 01434      }
 1435
 26701436      foreach (var toplevel in m.TopLevelDecls) {
 4451437        if (toplevel is ModuleDecl) {
 01438          var d = (ModuleDecl)toplevel;
 01439          dependencies.AddEdge(decl, d);
 01440          var subbindings = bindings.SubBindings(d.Name);
 01441          ProcessDependencies(d, subbindings ?? bindings, dependencies);
 01442          if (!m.IsAbstract && d is AbstractModuleDecl && ((AbstractModuleDecl)d).QId.Root != null) {
 01443            reporter.Error(MessageSource.Resolver, d.tok,
 01444              "The abstract import named {0} (using :) may only be used in an abstract module declaration",
 01445              d.Name);
 01446          }
 01447        }
 4451448      }
 4451449    }
 1450
 4451451    private void ProcessDependencies(ModuleDecl moduleDecl, ModuleBindings bindings, Graph<ModuleDecl> dependencies) {
 4451452      dependencies.AddVertex(moduleDecl);
 8901453      if (moduleDecl is LiteralModuleDecl) {
 4451454        ProcessDependenciesDefinition(moduleDecl, ((LiteralModuleDecl)moduleDecl).ModuleDef, bindings, dependencies);
 4451455      } else if (moduleDecl is AliasModuleDecl) {
 01456        var alias = moduleDecl as AliasModuleDecl;
 1457        ModuleDecl root;
 1458        // TryLookupFilter works outward, looking for a match to the filter for
 1459        // each enclosing module.
 01460        if (!ResolveQualifiedModuleIdRootImport(alias, bindings, alias.TargetQId, out root)) {
 1461          //        if (!bindings.TryLookupFilter(alias.TargetQId.rootToken(), out root, m => alias != m)
 01462          reporter.Error(MessageSource.Resolver, alias.tok, ModuleNotFoundErrorMessage(0, alias.TargetQId.Path));
 01463        } else {
 01464          dependencies.AddEdge(moduleDecl, root);
 01465        }
 01466      } else if (moduleDecl is AbstractModuleDecl) {
 01467        var abs = moduleDecl as AbstractModuleDecl;
 1468        ModuleDecl root;
 01469        if (!ResolveQualifiedModuleIdRootAbstract(abs, bindings, abs.QId, out root)) {
 1470          //if (!bindings.TryLookupFilter(abs.QId.rootToken(), out root,
 1471          //  m => abs != m && (((abs.EnclosingModuleDefinition == m.EnclosingModuleDefinition) && (abs.Exports.Count ==
 01472          reporter.Error(MessageSource.Resolver, abs.tok, ModuleNotFoundErrorMessage(0, abs.QId.Path));
 01473        } else {
 01474          dependencies.AddEdge(moduleDecl, root);
 01475        }
 01476      }
 4451477    }
 1478
 01479    private static string ModuleNotFoundErrorMessage(int i, List<Name> path, string tail = "") {
 1480      Contract.Requires(path != null);
 1481      Contract.Requires(0 <= i && i < path.Count);
 01482      return "module " + path[i].Value + " does not exist" +
 01483             (1 < path.Count
 01484               ? " (position " + i.ToString() + " in path " + Util.Comma(".", path, x => x.Value) + ")" + tail
 01485               : "");
 01486    }
 1487
 1488    private static bool EquivIfPresent<T1, T2>(Dictionary<T1, T2> dic, T1 key, T2 val)
 188501489      where T2 : class {
 1490      T2 val2;
 188501491      if (dic.TryGetValue(key, out val2)) {
 01492        return val.Equals(val2);
 1493      }
 1494
 188501495      return true;
 188501496    }
 1497
 8901498    public static ModuleSignature MergeSignature(ModuleSignature m, ModuleSignature system) {
 1499      Contract.Requires(m != null);
 1500      Contract.Requires(system != null);
 8901501      var info = new ModuleSignature();
 1502      // add the system-declared information, among which we know there are no duplicates
 906601503      foreach (var kv in system.TopLevels) {
 293301504        info.TopLevels.Add(kv.Key, kv.Value);
 293301505      }
 1506
 108601507      foreach (var kv in system.Ctors) {
 27301508        info.Ctors.Add(kv.Key, kv.Value);
 27301509      }
 1510
 26701511      foreach (var kv in system.StaticMembers) {
 01512        info.StaticMembers.Add(kv.Key, kv.Value);
 01513      }
 1514
 1515      // add for the module itself
 53401516      foreach (var kv in m.TopLevels) {
 8901517        if (info.TopLevels.TryGetValue(kv.Key, out var infoValue)) {
 01518          if (infoValue != kv.Value) {
 1519            // This only happens if one signature contains the name C as a class C (because it
 1520            // provides C) and the other signature contains the name C as a non-null type decl
 1521            // (because it reveals C and C?). The merge output will contain the non-null type decl
 1522            // for the key (and we expect the mapping "C? -> class C" to be placed in the
 1523            // merge output as well, by the end of this loop).
 01524            if (infoValue is ClassDecl) {
 01525              var cd = (ClassDecl)infoValue;
 01526              Contract.Assert(cd.NonNullTypeDecl == kv.Value);
 01527              info.TopLevels[kv.Key] = kv.Value;
 01528            } else if (kv.Value is ClassDecl) {
 01529              var cd = (ClassDecl)kv.Value;
 01530              Contract.Assert(cd.NonNullTypeDecl == infoValue);
 1531              // info.TopLevel[kv.Key] already has the right value
 01532            } else {
 01533              Contract.Assert(false); // unexpected
 01534            }
 1535
 01536            continue;
 1537          }
 01538        }
 1539
 8901540        info.TopLevels[kv.Key] = kv.Value;
 8901541      }
 1542
 26701543      foreach (var kv in m.Ctors) {
 01544        Contract.Assert(EquivIfPresent(info.Ctors, kv.Key, kv.Value));
 01545        info.Ctors[kv.Key] = kv.Value;
 01546      }
 1547
 592201548      foreach (var kv in m.StaticMembers) {
 188501549        Contract.Assert(EquivIfPresent(info.StaticMembers, kv.Key, kv.Value));
 188501550        info.StaticMembers[kv.Key] = kv.Value;
 188501551      }
 1552
 8901553      info.IsAbstract = m.IsAbstract;
 8901554      info.VisibilityScope = new VisibilityScope();
 8901555      info.VisibilityScope.Augment(m.VisibilityScope);
 8901556      info.VisibilityScope.Augment(system.VisibilityScope);
 8901557      return info;
 8901558    }
 1559
 1560    public static void ResolveOpenedImports(ModuleSignature sig, ModuleDefinition moduleDef, bool useCompileSignatures,
 8901561      Resolver resolver) {
 8901562      var declarations = sig.TopLevels.Values.ToList<TopLevelDecl>();
 8901563      var importedSigs = new HashSet<ModuleSignature>() { sig };
 1564
 8901565      var topLevelDeclReplacements = new List<TopLevelDecl>();
 933301566      foreach (var top in declarations) {
 302201567        if (top is ModuleDecl md && md.Opened) {
 01568          ResolveOpenedImportsWorker(sig, moduleDef, (ModuleDecl)top, importedSigs, useCompileSignatures, out var topLev
 01569          if (topLevelDeclReplacement != null) {
 01570            topLevelDeclReplacements.Add(topLevelDeclReplacement);
 01571          }
 01572        }
 302201573      }
 26701574      foreach (var topLevelDeclReplacement in topLevelDeclReplacements) {
 01575        if (sig.TopLevels.GetValueOrDefault(topLevelDeclReplacement.Name) is ModuleDecl moduleDecl) {
 01576          sig.ShadowedImportedModules[topLevelDeclReplacement.Name] = moduleDecl;
 01577        }
 01578        sig.TopLevels[topLevelDeclReplacement.Name] = topLevelDeclReplacement;
 01579      }
 1580
 17801581      if (resolver != null) {
 1582        //needed because ResolveOpenedImports is used statically for a refinement check
 8901583        if (sig.TopLevels["_default"] is AmbiguousTopLevelDecl) {
 01584          Contract.Assert(sig.TopLevels["_default"].WhatKind == "class");
 01585          var cl = new DefaultClassDecl(moduleDef, sig.StaticMembers.Values.ToList());
 01586          sig.TopLevels["_default"] = cl;
 01587          resolver.classMembers[cl] = cl.Members.ToDictionary(m => m.Name);
 01588        }
 8901589      }
 8901590    }
 1591
 01592    static TopLevelDecl ResolveAlias(TopLevelDecl dd) {
 01593      while (dd is AliasModuleDecl amd) {
 01594        dd = amd.TargetQId.Root;
 01595      }
 01596      return dd;
 01597    }
 1598
 1599    /// <summary>
 1600    /// Further populate "sig" with the accessible symbols from "im".
 1601    ///
 1602    /// Symbols declared locally in "moduleDef" take priority over any opened-import symbols, with one
 1603    /// exception:  for an "import opened M" where "M" contains a top-level symbol "M", unambiguously map the
 1604    /// name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mapping
 1605    /// to the caller, and let the caller remap the symbol after all opened imports have been processed.
 1606    /// </summary>
 1607    static void ResolveOpenedImportsWorker(ModuleSignature sig, ModuleDefinition moduleDef, ModuleDecl im, HashSet<Modul
 01608      bool useCompileSignatures, out TopLevelDecl topLevelDeclReplacement) {
 1609
 01610      topLevelDeclReplacement = null;
 01611      var s = GetSignatureExt(im.AccessibleSignature(useCompileSignatures), useCompileSignatures);
 1612
 01613      if (importedSigs.Contains(s)) {
 01614        return; // we've already got these declarations
 1615      }
 1616
 01617      importedSigs.Add(s);
 1618
 1619      // top-level declarations:
 01620      foreach (var kv in s.TopLevels) {
 01621        if (!kv.Value.CanBeExported()) {
 01622          continue;
 1623        }
 1624
 01625        if (!sig.TopLevels.TryGetValue(kv.Key, out var d)) {
 01626          sig.TopLevels.Add(kv.Key, kv.Value);
 01627        } else if (d.EnclosingModuleDefinition == moduleDef) {
 01628          if (kv.Value.EnclosingModuleDefinition.DafnyName != kv.Key) {
 1629            // declarations in the importing module take priority over opened-import declarations
 01630          } else {
 1631            // As an exception to the rule, for an "import opened M" that contains a top-level symbol "M", unambiguously
 1632            // name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mappi
 1633            // the caller, and let the caller remap the symbol after all opened imports have been processed.
 01634            topLevelDeclReplacement = kv.Value;
 01635          }
 01636        } else {
 01637          bool unambiguous = false;
 1638          // keep just one if they normalize to the same entity
 01639          if (d == kv.Value) {
 01640            unambiguous = true;
 01641          } else if (d is ModuleDecl || kv.Value is ModuleDecl) {
 01642            var dd = ResolveAlias(d);
 01643            var dk = ResolveAlias(kv.Value);
 01644            unambiguous = dd == dk;
 01645          } else {
 1646            // It's okay if "d" and "kv.Value" denote the same type. This can happen, for example,
 1647            // if both are type synonyms for "int".
 01648            var scope = Type.GetScope();
 01649            if (d.IsVisibleInScope(scope) && kv.Value.IsVisibleInScope(scope)) {
 01650              var dType = UserDefinedType.FromTopLevelDecl(d.tok, d);
 01651              var vType = UserDefinedType.FromTopLevelDecl(kv.Value.tok, kv.Value);
 01652              unambiguous = dType.Equals(vType, true);
 01653            }
 01654          }
 01655          if (!unambiguous) {
 01656            sig.TopLevels[kv.Key] = AmbiguousTopLevelDecl.Create(moduleDef, d, kv.Value);
 01657          }
 01658        }
 01659      }
 1660
 1661      // constructors:
 01662      foreach (var kv in s.Ctors) {
 01663        if (sig.Ctors.TryGetValue(kv.Key, out var pair)) {
 1664          // The same ctor can be imported from two different imports (e.g "diamond" imports), in which case,
 1665          // they are not duplicates.
 01666          if (!Object.ReferenceEquals(kv.Value.Item1, pair.Item1)) {
 1667            // mark it as a duplicate
 01668            sig.Ctors[kv.Key] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 01669          }
 01670        } else {
 1671          // add new
 01672          sig.Ctors.Add(kv.Key, kv.Value);
 01673        }
 01674      }
 1675
 1676      // static members:
 01677      foreach (var kv in s.StaticMembers) {
 01678        if (!kv.Value.CanBeExported()) {
 01679          continue;
 1680        }
 1681
 01682        if (sig.StaticMembers.TryGetValue(kv.Key, out var md)) {
 01683          sig.StaticMembers[kv.Key] = AmbiguousMemberDecl.Create(moduleDef, md, kv.Value);
 01684        } else {
 1685          // add new
 01686          sig.StaticMembers.Add(kv.Key, kv.Value);
 01687        }
 01688      }
 01689    }
 1690
 13351691    ModuleSignature RegisterTopLevelDecls(ModuleDefinition moduleDef, bool useImports) {
 1692      Contract.Requires(moduleDef != null);
 13351693      var sig = new ModuleSignature();
 13351694      sig.ModuleDef = moduleDef;
 13351695      sig.IsAbstract = moduleDef.IsAbstract;
 13351696      sig.VisibilityScope = new VisibilityScope();
 13351697      sig.VisibilityScope.Augment(moduleDef.VisibilityScope);
 1698
 13351699      List<TopLevelDecl> declarations = moduleDef.TopLevelDecls;
 1700
 1701      // This is solely used to detect duplicates amongst the various e
 13351702      Dictionary<string, TopLevelDecl> toplevels = new Dictionary<string, TopLevelDecl>();
 1703      // Now add the things present
 13351704      var anonymousImportCount = 0;
 480001705      foreach (TopLevelDecl d in declarations) {
 146651706        Contract.Assert(d != null);
 1707
 262151708        if (d is RevealableTypeDecl) {
 115501709          revealableTypes.Add((RevealableTypeDecl)d);
 115501710        }
 1711
 1712        // register the class/datatype/module name
 146651713        {
 146651714          TopLevelDecl registerThisDecl = null;
 146651715          string registerUnderThisName = null;
 146651716          if (d is ModuleExportDecl export) {
 01717            if (sig.ExportSets.ContainsKey(d.Name)) {
 01718              reporter.Error(MessageSource.Resolver, d, "duplicate name of export set: {0}", d.Name);
 01719            } else {
 01720              sig.ExportSets[d.Name] = export;
 01721            }
 146651722          } else if (d is AliasModuleDecl importDecl && importDecl.ShadowsLiteralModule) {
 1723            // add under an anonymous name
 01724            registerThisDecl = d;
 01725            registerUnderThisName = string.Format("{0}#{1}", d.Name, anonymousImportCount);
 01726            anonymousImportCount++;
 146651727          } else if (toplevels.ContainsKey(d.Name)) {
 01728            reporter.Error(MessageSource.Resolver, d, "duplicate name of top-level declaration: {0}", d.Name);
 155551729          } else if (d is ClassDecl cl && cl.NonNullTypeDecl != null) {
 8901730            registerThisDecl = cl.NonNullTypeDecl;
 8901731            registerUnderThisName = d.Name;
 146651732          } else {
 137751733            registerThisDecl = d;
 137751734            registerUnderThisName = d.Name;
 137751735          }
 1736
 293301737          if (registerThisDecl != null) {
 146651738            toplevels[registerUnderThisName] = registerThisDecl;
 146651739            sig.TopLevels[registerUnderThisName] = registerThisDecl;
 146651740          }
 146651741        }
 146651742        if (d is ModuleDecl) {
 1743          // nothing to do
 205651744        } else if (d is TypeSynonymDecl) {
 1745          // nothing more to register
 146651746        } else if (d is NewtypeDecl || d is AbstractTypeDecl) {
 01747          var cl = (TopLevelDeclWithMembers)d;
 1748          // register the names of the type members
 01749          var members = new Dictionary<string, MemberDecl>();
 01750          classMembers.Add(cl, members);
 01751          RegisterMembers(moduleDef, cl, members);
 87651752        } else if (d is IteratorDecl) {
 01753          var iter = (IteratorDecl)d;
 1754
 01755          iter.Resolve(this);
 130501756        } else if (d is ClassDecl) {
 42851757          var cl = (ClassDecl)d;
 42851758          var preMemberErrs = reporter.Count(ErrorLevel.Error);
 1759
 1760          // register the names of the class members
 42851761          var members = new Dictionary<string, MemberDecl>();
 42851762          classMembers.Add(cl, members);
 42851763          RegisterMembers(moduleDef, cl, members);
 1764
 42851765          Contract.Assert(preMemberErrs != reporter.Count(ErrorLevel.Error) ||
 42851766                          !cl.Members.Except(members.Values).Any());
 1767
 51751768          if (cl.IsDefaultClass) {
 592201769            foreach (MemberDecl m in members.Values) {
 188501770              Contract.Assert(!m.HasStaticKeyword || m is ConstantField); // note, the IsStatic value isn't available ye
 377001771              if (m is Function || m is Method || m is ConstantField) {
 188501772                sig.StaticMembers[m.Name] = m;
 188501773              }
 1774
 188501775              if (toplevels.ContainsKey(m.Name)) {
 01776                reporter.Error(MessageSource.Resolver, m.tok,
 01777                  $"duplicate declaration for name {m.Name}");
 01778              }
 188501779            }
 8901780          }
 1781
 101301782        } else if (d is DatatypeDecl) {
 13651783          var dt = (DatatypeDecl)d;
 1784
 1785          // register the names of the constructors
 13651786          dt.ConstructorsByName = new();
 1787          // ... and of the other members
 13651788          var members = new Dictionary<string, MemberDecl>();
 13651789          classMembers.Add(dt, members);
 1790
 81901791          foreach (DatatypeCtor ctor in dt.Ctors) {
 13651792            if (ctor.Name.EndsWith("?")) {
 01793              reporter.Error(MessageSource.Resolver, ctor,
 01794                "a datatype constructor name is not allowed to end with '?'");
 13651795            } else if (dt.ConstructorsByName.ContainsKey(ctor.Name)) {
 01796              reporter.Error(MessageSource.Resolver, ctor, "Duplicate datatype constructor name: {0}", ctor.Name);
 13651797            } else {
 13651798              dt.ConstructorsByName.Add(ctor.Name, ctor);
 13651799              ctor.InheritVisibility(dt);
 1800
 1801              // create and add the query "method" (field, really)
 13651802              var queryName = ctor.NameNode.Append("?");
 13651803              var query = new DatatypeDiscriminator(ctor.RangeToken, queryName, SpecialField.ID.UseIdParam, "is_" + ctor
 13651804                ctor.IsGhost, Type.Bool, null);
 13651805              query.InheritVisibility(dt);
 13651806              query.EnclosingClass = dt; // resolve here
 13651807              members.Add(queryName.Value, query);
 13651808              ctor.QueryField = query;
 1809
 1810              // also register the constructor name globally
 1811              Tuple<DatatypeCtor, bool> pair;
 13651812              if (sig.Ctors.TryGetValue(ctor.Name, out pair)) {
 1813                // mark it as a duplicate
 01814                sig.Ctors[ctor.Name] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 13651815              } else {
 1816                // add new
 13651817                sig.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 13651818              }
 13651819            }
 13651820          }
 1821
 1822          // add deconstructors now (that is, after the query methods have been added)
 81901823          foreach (DatatypeCtor ctor in dt.Ctors) {
 13651824            var formalsUsedInThisCtor = new HashSet<string>();
 13651825            var duplicates = new HashSet<Formal>();
 111901826            foreach (var formal in ctor.Formals) {
 23651827              MemberDecl previousMember = null;
 23651828              var localDuplicate = false;
 47301829              if (formal.HasName) {
 23651830                if (members.TryGetValue(formal.Name, out previousMember)) {
 01831                  localDuplicate = formalsUsedInThisCtor.Contains(formal.Name);
 01832                  if (localDuplicate) {
 01833                    reporter.Error(MessageSource.Resolver, ctor,
 01834                      "Duplicate use of deconstructor name in the same constructor: {0}", formal.Name);
 01835                    duplicates.Add(formal);
 01836                  } else if (previousMember is DatatypeDestructor) {
 1837                    // this is okay, if the destructor has the appropriate type; this will be checked later, after type 
 01838                  } else {
 01839                    reporter.Error(MessageSource.Resolver, ctor,
 01840                      "Name of deconstructor is used by another member of the datatype: {0}", formal.Name);
 01841                  }
 01842                }
 1843
 23651844                formalsUsedInThisCtor.Add(formal.Name);
 23651845              }
 1846
 1847              DatatypeDestructor dtor;
 23651848              if (!localDuplicate && previousMember is DatatypeDestructor) {
 1849                // a destructor with this name already existed in (a different constructor in) the datatype
 01850                dtor = (DatatypeDestructor)previousMember;
 01851                dtor.AddAnotherEnclosingCtor(ctor, formal);
 23651852              } else {
 1853                // either the destructor has no explicit name, or this constructor declared another destructor with this
 23651854                dtor = new DatatypeDestructor(formal.RangeToken, ctor, formal, new Name(formal.RangeToken, formal.Name),
 23651855                  formal.IsGhost, formal.Type, null);
 23651856                dtor.InheritVisibility(dt);
 23651857                dtor.EnclosingClass = dt; // resolve here
 47301858                if (formal.HasName && !localDuplicate && previousMember == null) {
 1859                  // the destructor has an explict name and there was no member at all with this name before
 23651860                  members.Add(formal.Name, dtor);
 23651861                }
 23651862              }
 1863
 23651864              ctor.Destructors.Add(dtor);
 23651865            }
 1866
 40951867            foreach (var duplicate in duplicates) {
 01868              ctor.Formals.Remove(duplicate);
 01869            }
 13651870          }
 1871
 1872          // finally, add any additional user-defined members
 13651873          RegisterMembers(moduleDef, dt, members);
 44801874        } else {
 31151875          Contract.Assert(d is ValuetypeDecl);
 31151876        }
 146651877      }
 1878
 1879      // Now, for each class, register its possibly-null type
 480001880      foreach (TopLevelDecl d in declarations) {
 155551881        if ((d as ClassDecl)?.NonNullTypeDecl != null) {
 8901882          var name = d.Name + "?";
 1883          TopLevelDecl prev;
 8901884          if (toplevels.TryGetValue(name, out prev)) {
 01885            reporter.Error(MessageSource.Resolver, d,
 01886              "a module that already contains a top-level declaration '{0}' is not allowed to declare a {1} '{2}'",
 01887              name, d.WhatKind, d.Name);
 8901888          } else {
 8901889            toplevels[name] = d;
 8901890            sig.TopLevels[name] = d;
 8901891          }
 8901892        }
 146651893      }
 1894
 13351895      return sig;
 13351896    }
 1897
 1898    void RegisterMembers(ModuleDefinition moduleDef, TopLevelDeclWithMembers cl,
 56501899      Dictionary<string, MemberDecl> members) {
 1900      Contract.Requires(moduleDef != null);
 1901      Contract.Requires(cl != null);
 1902      Contract.Requires(members != null);
 1903
 898651904      foreach (MemberDecl m in cl.Members) {
 486101905        if (!members.ContainsKey(m.Name)) {
 243051906          members.Add(m.Name, m);
 243051907          if (m is Constructor) {
 01908            Contract.Assert(cl is ClassDecl); // the parser ensures this condition
 01909            if (cl is TraitDecl) {
 01910              reporter.Error(MessageSource.Resolver, m.tok, "a trait is not allowed to declare a constructor");
 01911            } else {
 01912              ((ClassDecl)cl).HasConstructor = true;
 01913            }
 243051914          } else if (m is ExtremePredicate || m is ExtremeLemma) {
 01915            var extraName = m.NameNode.Append("#");
 1916            MemberDecl extraMember;
 01917            var cloner = new Cloner();
 01918            var formals = new List<Formal>();
 1919            Type typeOfK;
 01920            if ((m is ExtremePredicate && ((ExtremePredicate)m).KNat) ||
 01921                (m is ExtremeLemma && ((ExtremeLemma)m).KNat)) {
 01922              typeOfK = new UserDefinedType(m.tok, "nat", (List<Type>)null);
 01923            } else {
 01924              typeOfK = new BigOrdinalType();
 01925            }
 1926
 01927            var k = new ImplicitFormal(m.tok, "_k", typeOfK, true, false);
 01928            reporter.Info(MessageSource.Resolver, m.tok, string.Format("_k: {0}", k.Type));
 01929            formals.Add(k);
 01930            if (m is ExtremePredicate extremePredicate) {
 01931              formals.AddRange(extremePredicate.Formals.ConvertAll(f => cloner.CloneFormal(f, false)));
 1932
 01933              List<TypeParameter> tyvars = extremePredicate.TypeArgs.ConvertAll(cloner.CloneTypeParam);
 1934
 1935              // create prefix predicate
 01936              extremePredicate.PrefixPredicate = new PrefixPredicate(extremePredicate.RangeToken, extraName, extremePred
 01937                tyvars, k, formals,
 01938                extremePredicate.Req.ConvertAll(cloner.CloneAttributedExpr),
 01939                extremePredicate.Reads.ConvertAll(cloner.CloneFrameExpr),
 01940                extremePredicate.Ens.ConvertAll(cloner.CloneAttributedExpr),
 01941                new Specification<Expression>(new List<Expression>() { new IdentifierExpr(extremePredicate.tok, k.Name) 
 01942                cloner.CloneExpr(extremePredicate.Body),
 01943                null,
 01944                extremePredicate);
 01945              extraMember = extremePredicate.PrefixPredicate;
 01946            } else {
 01947              var extremeLemma = (ExtremeLemma)m;
 1948              // _k has already been added to 'formals', so append the original formals
 01949              formals.AddRange(extremeLemma.Ins.ConvertAll(f => cloner.CloneFormal(f, false)));
 1950              // prepend _k to the given decreases clause
 01951              var decr = new List<Expression>();
 01952              decr.Add(new IdentifierExpr(extremeLemma.tok, k.Name));
 01953              decr.AddRange(extremeLemma.Decreases.Expressions.ConvertAll(cloner.CloneExpr));
 1954              // Create prefix lemma.  Note that the body is not cloned, but simply shared.
 1955              // For a greatest lemma, the postconditions are filled in after the greatest lemma's postconditions have b
 1956              // For a least lemma, the preconditions are filled in after the least lemma's preconditions have been reso
 01957              var req = extremeLemma is GreatestLemma
 01958                ? extremeLemma.Req.ConvertAll(cloner.CloneAttributedExpr)
 01959                : new List<AttributedExpression>();
 01960              var ens = extremeLemma is GreatestLemma
 01961                ? new List<AttributedExpression>()
 01962                : extremeLemma.Ens.ConvertAll(cloner.CloneAttributedExpr);
 01963              extremeLemma.PrefixLemma = new PrefixLemma(extremeLemma.RangeToken, extraName, extremeLemma.HasStaticKeywo
 01964                extremeLemma.TypeArgs.ConvertAll(cloner.CloneTypeParam), k, formals, extremeLemma.Outs.ConvertAll(f => c
 01965                req, cloner.CloneSpecFrameExpr(extremeLemma.Mod), ens,
 01966                new Specification<Expression>(decr, null),
 01967                null, // Note, the body for the prefix method will be created once the call graph has been computed and 
 01968                cloner.CloneAttributes(extremeLemma.Attributes), extremeLemma);
 01969              extraMember = extremeLemma.PrefixLemma;
 01970            }
 1971
 01972            extraMember.InheritVisibility(m, false);
 01973            members.Add(extraName.Value, extraMember);
 243051974          } else if (m is Function f && f.ByMethodBody != null) {
 01975            RegisterByMethod(f, cl);
 01976          }
 243051977        } else if (m is Constructor && !((Constructor)m).HasName) {
 01978          reporter.Error(MessageSource.Resolver, m, "More than one anonymous constructor");
 01979        } else {
 01980          reporter.Error(MessageSource.Resolver, m, "Duplicate member name: {0}", m.Name);
 01981        }
 243051982      }
 56501983    }
 1984
 01985    void RegisterByMethod(Function f, TopLevelDeclWithMembers cl) {
 1986      Contract.Requires(f != null && f.ByMethodBody != null);
 1987
 01988      var tok = f.ByMethodTok;
 01989      var resultVar = f.Result ?? new Formal(tok, "#result", f.ResultType, false, false, null);
 01990      var r = Expression.CreateIdentExpr(resultVar);
 01991      var receiver = f.IsStatic ? (Expression)new StaticReceiverExpr(tok, cl, true) : new ImplicitThisExpr(tok);
 01992      var fn = new FunctionCallExpr(tok, f.Name, receiver, tok, tok, f.Formals.ConvertAll(Expression.CreateIdentExpr));
 01993      var post = new AttributedExpression(new BinaryExpr(tok, BinaryExpr.Opcode.Eq, r, fn));
 01994      var method = new Method(f.RangeToken, f.NameNode, f.HasStaticKeyword, false, f.TypeArgs,
 01995        f.Formals, new List<Formal>() { resultVar },
 01996        f.Req, new Specification<FrameExpression>(new List<FrameExpression>(), null), new List<AttributedExpression>() {
 01997        f.ByMethodBody, f.Attributes, null, true);
 01998      Contract.Assert(f.ByMethodDecl == null);
 01999      method.InheritVisibility(f);
 02000      method.FunctionFromWhichThisIsByMethodDecl = f;
 02001      f.ByMethodDecl = method;
 02002    }
 2003
 2004    private ModuleSignature MakeAbstractSignature(ModuleSignature p, string Name, int Height,
 2005      Dictionary<ModuleDefinition, ModuleSignature> mods,
 02006      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2007      Contract.Requires(p != null);
 2008      Contract.Requires(Name != null);
 2009      Contract.Requires(mods != null);
 2010      Contract.Requires(compilationModuleClones != null);
 02011      var errCount = reporter.Count(ErrorLevel.Error);
 2012
 02013      var mod = new ModuleDefinition(RangeToken.NoToken, new Name(Name + ".Abs"), new List<IToken>(), true, true, null, 
 02014        false,
 02015        p.ModuleDef.IsToBeVerified, p.ModuleDef.IsToBeCompiled);
 02016      mod.Height = Height;
 02017      bool hasDefaultClass = false;
 02018      foreach (var kv in p.TopLevels) {
 02019        hasDefaultClass = kv.Value is DefaultClassDecl || hasDefaultClass;
 02020        if (!(kv.Value is NonNullTypeDecl)) {
 02021          var clone = CloneDeclaration(p.VisibilityScope, kv.Value, mod, mods, Name, compilationModuleClones);
 02022          mod.TopLevelDecls.Add(clone);
 02023        }
 02024      }
 2025
 02026      if (!hasDefaultClass) {
 02027        DefaultClassDecl cl = new DefaultClassDecl(mod, p.StaticMembers.Values.ToList());
 02028        mod.TopLevelDecls.Add(CloneDeclaration(p.VisibilityScope, cl, mod, mods, Name, compilationModuleClones));
 02029      }
 2030
 02031      var sig = RegisterTopLevelDecls(mod, true);
 02032      sig.Refines = p.Refines;
 02033      sig.CompileSignature = p;
 02034      sig.IsAbstract = p.IsAbstract;
 02035      mods.Add(mod, sig);
 02036      var good = ResolveModuleDefinition(mod, sig);
 02037      if (good && reporter.Count(ErrorLevel.Error) == errCount) {
 02038        mod.SuccessfullyResolved = true;
 02039      }
 2040
 02041      return sig;
 02042    }
 2043
 2044    TopLevelDecl CloneDeclaration(VisibilityScope scope, TopLevelDecl d, ModuleDefinition m,
 2045      Dictionary<ModuleDefinition, ModuleSignature> mods, string Name,
 02046      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2047      Contract.Requires(d != null);
 2048      Contract.Requires(m != null);
 2049      Contract.Requires(mods != null);
 2050      Contract.Requires(Name != null);
 2051      Contract.Requires(compilationModuleClones != null);
 2052
 02053      if (d is AbstractModuleDecl) {
 02054        var abs = (AbstractModuleDecl)d;
 02055        var sig = MakeAbstractSignature(abs.OriginalSignature, Name + "." + abs.Name, abs.Height, mods,
 02056          compilationModuleClones);
 02057        var a = new AbstractModuleDecl(abs.RangeToken, abs.QId, abs.NameNode, m, abs.Opened, abs.Exports);
 02058        a.Signature = sig;
 02059        a.OriginalSignature = abs.OriginalSignature;
 02060        return a;
 02061      } else {
 02062        return new AbstractSignatureCloner(scope).CloneDeclaration(d, m);
 2063      }
 02064    }
 2065
 2066    // Returns the resolved Module declaration corresponding to the qualified module id
 2067    // Requires the root to have been resolved
 2068    // Issues an error and returns null if the path is not valid
 02069    public ModuleDecl ResolveModuleQualifiedId(ModuleDecl root, ModuleQualifiedId qid, ErrorReporter reporter) {
 2070
 2071      Contract.Requires(qid != null);
 2072      Contract.Requires(qid.Path.Count > 0);
 2073
 02074      List<Name> Path = qid.Path;
 02075      ModuleDecl decl = root;
 2076      ModuleSignature p;
 02077      for (int k = 1; k < Path.Count; k++) {
 02078        if (decl is LiteralModuleDecl) {
 02079          p = ((LiteralModuleDecl)decl).DefaultExport;
 02080          if (p == null) {
 02081            reporter.Error(MessageSource.Resolver, Path[k],
 02082              ModuleNotFoundErrorMessage(k, Path, $" because {decl.Name} does not have a default export"));
 02083            return null;
 2084          }
 02085        } else {
 02086          p = decl.Signature;
 02087        }
 2088
 02089        var tld = p.TopLevels.GetValueOrDefault(Path[k].Value, null);
 02090        if (!(tld is ModuleDecl dd)) {
 02091          if (decl.Signature.ModuleDef == null) {
 02092            reporter.Error(MessageSource.Resolver, Path[k],
 02093              ModuleNotFoundErrorMessage(k, Path, " because of previous error"));
 02094          } else {
 02095            reporter.Error(MessageSource.Resolver, Path[k], ModuleNotFoundErrorMessage(k, Path));
 02096          }
 02097          return null;
 2098        }
 2099
 2100        // Any aliases along the qualified path ought to be already resolved,
 2101        // else the modules are not being resolved in the right order
 02102        if (dd is AliasModuleDecl amd) {
 02103          Contract.Assert(amd.Signature != null);
 02104        }
 02105        decl = dd;
 02106      }
 2107
 02108      return decl;
 02109    }
 2110
 2111
 2112    public bool ResolveExport(ModuleDecl alias, ModuleDefinition parent, ModuleQualifiedId qid,
 02113      List<IToken> Exports, out ModuleSignature p, ErrorReporter reporter) {
 2114      Contract.Requires(qid != null);
 2115      Contract.Requires(qid.Path.Count > 0);
 2116      Contract.Requires(Exports != null);
 2117
 02118      ModuleDecl root = qid.Root;
 02119      ModuleDecl decl = ResolveModuleQualifiedId(root, qid, reporter);
 02120      if (decl == null) {
 02121        p = null;
 02122        return false;
 2123      }
 02124      p = decl.Signature;
 02125      if (Exports.Count == 0) {
 02126        if (p.ExportSets.Count == 0) {
 02127          if (decl is LiteralModuleDecl) {
 02128            p = ((LiteralModuleDecl)decl).DefaultExport;
 02129          } else {
 2130            // p is OK
 02131          }
 02132        } else {
 02133          var m = p.ExportSets.GetValueOrDefault(decl.Name, null);
 02134          if (m == null) {
 2135            // no default view is specified.
 02136            reporter.Error(MessageSource.Resolver, qid.rootToken(), "no default export set declared in module: {0}", dec
 02137            return false;
 2138          }
 02139          p = m.AccessibleSignature();
 02140        }
 02141      } else {
 2142        ModuleExportDecl pp;
 02143        if (decl.Signature.ExportSets.TryGetValue(Exports[0].val, out pp)) {
 02144          p = pp.AccessibleSignature();
 02145        } else {
 02146          reporter.Error(MessageSource.Resolver, Exports[0], "no export set '{0}' in module '{1}'", Exports[0].val, decl
 02147          p = null;
 02148          return false;
 2149        }
 2150
 02151        foreach (IToken export in Exports.Skip(1)) {
 02152          if (decl.Signature.ExportSets.TryGetValue(export.val, out pp)) {
 02153            Contract.Assert(Object.ReferenceEquals(p.ModuleDef, pp.Signature.ModuleDef));
 02154            ModuleSignature merged = MergeSignature(p, pp.Signature);
 02155            merged.ModuleDef = pp.Signature.ModuleDef;
 02156            if (p.CompileSignature != null) {
 02157              Contract.Assert(pp.Signature.CompileSignature != null);
 02158              merged.CompileSignature = MergeSignature(p.CompileSignature, pp.Signature.CompileSignature);
 02159            } else {
 02160              Contract.Assert(pp.Signature.CompileSignature == null);
 02161            }
 02162            p = merged;
 02163          } else {
 02164            reporter.Error(MessageSource.Resolver, export, "no export set {0} in module {1}", export.val, decl.Name);
 02165            p = null;
 02166            return false;
 2167          }
 02168        }
 02169      }
 02170      return true;
 02171    }
 2172
 13352173    public void RevealAllInScope(List<TopLevelDecl> declarations, VisibilityScope scope) {
 480002174      foreach (TopLevelDecl d in declarations) {
 146652175        d.AddVisibilityScope(scope, false);
 203152176        if (d is TopLevelDeclWithMembers) {
 56502177          var cl = (TopLevelDeclWithMembers)d;
 898652178          foreach (var mem in cl.Members) {
 486102179            if (!mem.ScopeIsInherited) {
 243052180              mem.AddVisibilityScope(scope, false);
 243052181            }
 243052182          }
 56502183          var nnd = (cl as ClassDecl)?.NonNullTypeDecl;
 65402184          if (nnd != null) {
 8902185            nnd.AddVisibilityScope(scope, false);
 8902186          }
 56502187        }
 146652188      }
 13352189    }
 2190
 8902191    public void ResolveTopLevelDecls_Signatures(ModuleDefinition def, ModuleSignature sig, List<TopLevelDecl/*!*/>/*!*/ 
 2192      Contract.Requires(declarations != null);
 2193      Contract.Requires(datatypeDependencies != null);
 2194      Contract.Requires(codatatypeDependencies != null);
 8902195      RevealAllInScope(declarations, def.VisibilityScope);
 2196
 2197      /* Augment the scoping environment for the current module*/
 53402198      foreach (TopLevelDecl d in declarations) {
 8902199        if (d is ModuleDecl && !(d is ModuleExportDecl)) {
 02200          var decl = (ModuleDecl)d;
 02201          moduleInfo.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02202          sig.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02203        }
 8902204      }
 2205      /*if (sig.Refines != null) {
 2206        moduleInfo.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2207        sig.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2208      }*/
 2209
 8902210      var typeRedirectionDependencies = new Graph<RedirectingTypeDecl>();  // this concerns the type directions, not the
 53402211      foreach (TopLevelDecl d in declarations) {
 8902212        Contract.Assert(d != null);
 8902213        allTypeParameters.PushMarker();
 8902214        ResolveTypeParameters(d.TypeArgs, true, d);
 8902215        if (d is TypeSynonymDecl) {
 02216          var dd = (TypeSynonymDecl)d;
 02217          ResolveType(dd.tok, dd.Rhs, dd, ResolveTypeOptionEnum.AllowPrefix, dd.TypeArgs);
 02218          dd.Rhs.ForeachTypeComponent(ty => {
 02219            var s = ty.AsRedirectingType;
 02220            if (s != null && s != dd) {
 02221              typeRedirectionDependencies.AddEdge(dd, s);
 02222            }
 02223          });
 8902224        } else if (d is NewtypeDecl) {
 02225          var dd = (NewtypeDecl)d;
 02226          ResolveType(dd.tok, dd.BaseType, dd, ResolveTypeOptionEnum.DontInfer, null);
 02227          dd.BaseType.ForeachTypeComponent(ty => {
 02228            var s = ty.AsRedirectingType;
 02229            if (s != null && s != dd) {
 02230              typeRedirectionDependencies.AddEdge(dd, s);
 02231            }
 02232          });
 02233          ResolveClassMemberTypes(dd);
 8902234        } else if (d is IteratorDecl) {
 02235          ResolveIteratorSignature((IteratorDecl)d);
 8902236        } else if (d is ModuleDecl) {
 02237          var decl = (ModuleDecl)d;
 02238          if (!def.IsAbstract && decl is AliasModuleDecl am && decl.Signature.IsAbstract) {
 02239            reporter.Error(MessageSource.Resolver, am.TargetQId.rootToken(), "a compiled module ({0}) is not allowed to 
 02240          }
 8902241        } else if (d is DatatypeDecl) {
 02242          var dd = (DatatypeDecl)d;
 02243          ResolveCtorTypes(dd, datatypeDependencies, codatatypeDependencies);
 02244          ResolveClassMemberTypes(dd);
 8902245        } else {
 8902246          ResolveClassMemberTypes((TopLevelDeclWithMembers)d);
 8902247        }
 8902248        allTypeParameters.PopMarker();
 8902249      }
 2250
 2251      // Resolve the parent-trait types and fill in .ParentTraitHeads
 8902252      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 8902253      var parentRelation = new Graph<TopLevelDeclWithMembers>();
 53402254      foreach (TopLevelDecl d in declarations) {
 17802255        if (d is TopLevelDeclWithMembers cl) {
 8902256          ResolveParentTraitTypes(cl, parentRelation);
 8902257        }
 8902258      }
 2259      // Check for cycles among parent traits
 26702260      foreach (var cycle in parentRelation.AllCycles()) {
 02261        ReportCycleError(cycle, m => m.tok, m => m.Name, "trait definitions contain a cycle");
 02262      }
 17802263      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2264        // Register the trait members in the classes that inherit them
 53402265        foreach (TopLevelDecl d in declarations) {
 17802266          if (d is TopLevelDeclWithMembers cl) {
 8902267            RegisterInheritedMembers(cl);
 8902268          }
 8902269        }
 8902270      }
 17802271      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2272        // Now that all traits have been resolved, let classes inherit the trait members
 53402273        foreach (var d in declarations) {
 17802274          if (d is TopLevelDeclWithMembers cl) {
 8902275            InheritedTraitMembers(cl);
 8902276          }
 8902277        }
 8902278      }
 2279
 2280      // perform acyclicity test on type synonyms
 26702281      foreach (var cycle in typeRedirectionDependencies.AllCycles()) {
 02282        ReportCycleError(cycle, rtd => rtd.tok, rtd => rtd.Name, "cycle among redirecting types (newtypes, subset types,
 02283      }
 8902284    }
 2285
 02286    public static readonly List<NativeType> NativeTypes = new List<NativeType>() {
 02287      new NativeType("byte", 0, 0x100, 8, NativeType.Selection.Byte),
 02288      new NativeType("sbyte", -0x80, 0x80, 0, NativeType.Selection.SByte),
 02289      new NativeType("ushort", 0, 0x1_0000, 16, NativeType.Selection.UShort),
 02290      new NativeType("short", -0x8000, 0x8000, 0, NativeType.Selection.Short),
 02291      new NativeType("uint", 0, 0x1_0000_0000, 32, NativeType.Selection.UInt),
 02292      new NativeType("int", -0x8000_0000, 0x8000_0000, 0, NativeType.Selection.Int),
 02293      new NativeType("number", -0x1f_ffff_ffff_ffff, 0x20_0000_0000_0000, 0, NativeType.Selection.Number),  // JavaScrip
 02294      new NativeType("ulong", 0, new BigInteger(0x1_0000_0000) * new BigInteger(0x1_0000_0000), 64, NativeType.Selection
 02295      new NativeType("long", Int64.MinValue, 0x8000_0000_0000_0000, 0, NativeType.Selection.Long),
 02296    };
 2297
 2298    public void ResolveTopLevelDecls_Core(List<TopLevelDecl> declarations,
 2299      Graph<IndDatatypeDecl> datatypeDependencies, Graph<CoDatatypeDecl> codatatypeDependencies,
 13352300      string moduleName, bool isAnExport = false) {
 2301
 2302      Contract.Requires(declarations != null);
 2303      Contract.Requires(cce.NonNullElements(datatypeDependencies.GetVertices()));
 2304      Contract.Requires(cce.NonNullElements(codatatypeDependencies.GetVertices()));
 2305      Contract.Requires(AllTypeConstraints.Count == 0);
 2306
 2307      Contract.Ensures(AllTypeConstraints.Count == 0);
 2308
 13352309      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 2310
 2311      // ---------------------------------- Pass 0 ----------------------------------
 2312      // This pass:
 2313      // * resolves names, introduces (and may solve) type constraints
 2314      // * checks that all types were properly inferred
 2315      // * fills in .ResolvedOp fields
 2316      // * perform substitution for DefaultValueExpression's
 2317      // ----------------------------------------------------------------------------
 2318
 13352319      if (Options.Get(CommonOptionBag.TypeSystemRefresh)) {
 2320        // Resolve all names and infer types.
 02321        var preTypeResolver = new PreTypeResolver(this);
 02322        preTypeResolver.ResolveDeclarations(declarations, moduleName);
 2323
 02324        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02325          var u = new UnderspecificationDetector(this);
 02326          u.Check(declarations);
 02327        }
 2328
 02329        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02330          new PreTypeToTypeVisitor().VisitDeclarations(declarations);
 02331        }
 2332
 13352333      } else {
 2334        // Resolve all names and infer types. These two are done together, because name resolution depends on having typ
 2335        // and type inference depends on having resolved names.
 2336        // The task is first performed for (the constraints of) newtype declarations, (the constraints of) subset type d
 2337        // (the right-hand sides of) const declarations, because type resolution sometimes needs to know the base type o
 2338        // and needs to know the type of const fields. Doing these declarations increases the chances the right informat
 2339        // in time.
 2340        // Once the task is done for these newtype/subset-type/const parts, the task continues with everything else.
 13352341        ResolveNamesAndInferTypes(declarations, true);
 13352342        ResolveNamesAndInferTypes(declarations, false);
 13352343      }
 2344
 2345      // Check that all types have been determined. During this process, also fill in all .ResolvedOp fields.
 26702346      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 13352347        var checkTypeInferenceVisitor = new CheckTypeInferenceVisitor(this);
 13352348        checkTypeInferenceVisitor.VisitDeclarations(declarations);
 13352349      }
 2350
 2351      // Substitute for DefaultValueExpression's
 13352352      FillInDefaultValueExpressions();
 2353
 2354      // ---------------------------------- Pass 1 ----------------------------------
 2355      // This pass does the following:
 2356      // * desugar functions used in reads clauses
 2357      // * compute .BodySurrogate for body-less loops
 2358      // * discovers bounds
 2359      // * builds the module's call graph.
 2360      // * compute and checks ghosts (this makes use of bounds discovery, as done above)
 2361      // * for newtypes, figure out native types
 2362      // * for datatypes, check that shared destructors are in agreement in ghost matters
 2363      // * for functions and methods, determine tail recursion
 2364      // ----------------------------------------------------------------------------
 2365
 2366      // Discover bounds. These are needed later to determine if certain things are ghost or compiled,
 2367      // and thus this should be done before building the call graph.
 2368      // The BoundsDiscoveryVisitor also desugars FrameExpressions, so that bounds discovery can
 2369      // apply to the desugared versions.
 2370      // This pass also computes body surrogates for body-less loops, which is a bit like desugaring
 2371      // such loops.
 26702372      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 13352373        var boundsDiscoveryVisitor = new BoundsDiscoveryVisitor(reporter);
 13352374        boundsDiscoveryVisitor.VisitDeclarations(declarations);
 13352375      }
 2376
 26702377      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 13352378        CallGraphBuilder.Build(declarations, reporter);
 13352379      }
 2380
 2381      // Compute ghost interests, figure out native types, check agreement among datatype destructors, and determine tai
 26702382      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 120152383        foreach (TopLevelDecl d in declarations) {
 26702384          if (d is IteratorDecl) {
 02385            var iter = (IteratorDecl)d;
 02386            iter.SubExpressions.Iter(e => CheckExpression(e, this, iter));
 02387            if (iter.Body != null) {
 02388              ComputeGhostInterest(iter.Body, false, null, iter);
 02389              CheckExpression(iter.Body, this, iter);
 02390            }
 2391
 35602392          } else if (d is SubsetTypeDecl subsetTypeDecl) {
 8902393            Contract.Assert(subsetTypeDecl.Constraint != null);
 8902394            CheckExpression(subsetTypeDecl.Constraint, this, new CodeContextWrapper(subsetTypeDecl, true));
 8902395            subsetTypeDecl.ConstraintIsCompilable =
 8902396              ExpressionTester.CheckIsCompilable(Options, null, subsetTypeDecl.Constraint, new CodeContextWrapper(subset
 8902397            subsetTypeDecl.CheckedIfConstraintIsCompilable = true;
 2398
 8902399            if (subsetTypeDecl.Witness != null) {
 02400              CheckExpression(subsetTypeDecl.Witness, this, new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.Witnes
 02401              if (subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02402                var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WK
 02403                ExpressionTester.CheckIsCompilable(Options, this, subsetTypeDecl.Witness, codeContext);
 02404              }
 02405            }
 2406
 26702407          } else if (d is NewtypeDecl newtypeDecl) {
 02408            if (newtypeDecl.Var != null) {
 02409              Contract.Assert(newtypeDecl.Constraint != null);
 02410              CheckExpression(newtypeDecl.Constraint, this, new CodeContextWrapper(newtypeDecl, true));
 02411              if (newtypeDecl.Witness != null) {
 02412                CheckExpression(newtypeDecl.Witness, this, new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind =
 02413              }
 02414            }
 02415            if (newtypeDecl.Witness != null && newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02416              var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghos
 02417              ExpressionTester.CheckIsCompilable(Options, this, newtypeDecl.Witness, codeContext);
 02418            }
 2419
 02420            FigureOutNativeType(newtypeDecl);
 2421
 17802422          } else if (d is DatatypeDecl) {
 02423            var dd = (DatatypeDecl)d;
 02424            foreach (var member in classMembers[dd].Values) {
 02425              var dtor = member as DatatypeDestructor;
 02426              if (dtor != null) {
 02427                var rolemodel = dtor.CorrespondingFormals[0];
 02428                for (int i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 02429                  var other = dtor.CorrespondingFormals[i];
 02430                  if (rolemodel.IsGhost != other.IsGhost) {
 02431                    reporter.Error(MessageSource.Resolver, other,
 02432                      "shared destructors must agree on whether or not they are ghost, but '{0}' is {1} in constructor '
 02433                      rolemodel.Name,
 02434                      rolemodel.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[0].Name,
 02435                      other.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[i].Name);
 02436                  }
 02437                }
 02438              }
 02439            }
 02440            foreach (var ctor in dd.Ctors) {
 02441              CheckParameterDefaultValuesAreCompilable(ctor.Formals, dd);
 02442            }
 02443          }
 2444
 44502445          if (d is TopLevelDeclWithMembers cl) {
 17802446            ResolveClassMembers_Pass1(cl);
 17802447          }
 26702448        }
 13352449      }
 2450
 2451      // ---------------------------------- Pass 2 ----------------------------------
 2452      // This pass fills in various additional information.
 2453      // * Subset type in comprehensions have a compilable constraint
 2454      // * Postconditions and bodies of prefix lemmas
 2455      // * Compute postconditions and statement body of prefix lemmas
 2456      // * Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes req
 2457      // * Set the SccRepr field of codatatypes
 2458      // * Perform the guardedness check on co-datatypes
 2459      // * Do datatypes and type synonyms until a fixpoint is reached, same for functions and methods
 2460      // * Check that functions claiming to be abstemious really are
 2461      // * Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2462      // * Extreme predicate recursivity checks
 2463      // * Verify that subset constraints are compilable if necessary
 2464      // ----------------------------------------------------------------------------
 2465
 26702466      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2467        // fill in the postconditions and bodies of prefix lemmas
 13352468        FillInPostConditionsAndBodiesOfPrefixLemmas(declarations);
 13352469      }
 2470
 2471      // Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes requi
 40052472      foreach (var dtd in datatypeDependencies.TopologicallySortedComponents()) {
 02473        if (datatypeDependencies.GetSCCRepresentative(dtd) == dtd) {
 2474          // do the following check once per SCC, so call it on each SCC representative
 02475          SccStratosphereCheck(dtd, datatypeDependencies);
 02476          DetermineEqualitySupport(dtd, datatypeDependencies);
 02477        }
 02478      }
 2479
 2480      // Set the SccRepr field of codatatypes
 40052481      foreach (var repr in codatatypeDependencies.TopologicallySortedComponents()) {
 02482        foreach (var codt in codatatypeDependencies.GetSCC(repr)) {
 02483          codt.SscRepr = repr;
 02484        }
 02485      }
 2486
 26702487      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {  // because CheckCoCalls requires the given expression t
 2488        // Perform the guardedness check on co-datatypes
 451352489        foreach (var repr in ModuleDefinition.AllFunctionSCCs(declarations)) {
 137102490          var module = repr.EnclosingModule;
 137102491          bool dealsWithCodatatypes = false;
 822602492          foreach (var m in module.CallGraph.GetSCC(repr)) {
 137102493            var f = m as Function;
 137102494            if (f != null && f.ResultType.InvolvesCoDatatype) {
 02495              dealsWithCodatatypes = true;
 02496              break;
 2497            }
 137102498          }
 137102499          var coCandidates = new List<CoCallResolution.CoCallInfo>();
 137102500          var hasIntraClusterCallsInDestructiveContexts = false;
 822602501          foreach (var m in module.CallGraph.GetSCC(repr)) {
 137102502            var f = m as Function;
 274202503            if (f != null && f.Body != null) {
 137102504              var checker = new CoCallResolution(f, dealsWithCodatatypes);
 137102505              checker.CheckCoCalls(f.Body);
 137102506              coCandidates.AddRange(checker.FinalCandidates);
 137102507              hasIntraClusterCallsInDestructiveContexts |= checker.HasIntraClusterCallsInDestructiveContexts;
 137102508            } else if (f == null) {
 2509              // the SCC contains a method, which we always consider to be a destructive context
 02510              hasIntraClusterCallsInDestructiveContexts = true;
 02511            }
 137102512          }
 137102513          if (coCandidates.Count != 0) {
 02514            if (hasIntraClusterCallsInDestructiveContexts) {
 02515              foreach (var c in coCandidates) {
 02516                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsInDestructiveContext;
 02517              }
 02518            } else {
 02519              foreach (var c in coCandidates) {
 02520                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 02521                c.EnclosingCoConstructor.IsCoCall = true;
 02522                reporter.Info(MessageSource.Resolver, c.CandidateCall.tok, "co-recursive call");
 02523              }
 2524              // Finally, fill in the CoClusterTarget field
 2525              // Start by setting all the CoClusterTarget fields to CoRecursiveTargetAllTheWay.
 02526              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02527                var f = (Function)m;  // the cast is justified on account of that we allow co-recursive calls only in cl
 02528                f.CoClusterTarget = Function.CoCallClusterInvolvement.CoRecursiveTargetAllTheWay;
 02529              }
 2530              // Then change the field to IsMutuallyRecursiveTarget whenever we see a non-self recursive non-co-recursiv
 02531              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02532                var f = (Function)m;  // cast is justified just like above
 02533                foreach (var call in f.AllCalls) {
 02534                  if (call.CoCall != FunctionCallExpr.CoCallResolution.Yes && call.Function != f && ModuleDefinition.InS
 02535                    call.Function.CoClusterTarget = Function.CoCallClusterInvolvement.IsMutuallyRecursiveTarget;
 02536                  }
 02537                }
 02538              }
 02539            }
 02540          }
 137102541        }
 2542        // Inferred required equality support for datatypes and type synonyms, and for Function and Method signatures.
 2543        // First, do datatypes and type synonyms until a fixpoint is reached.
 2544        bool inferredSomething;
 13352545        do {
 13352546          inferredSomething = false;
 120152547          foreach (var d in declarations) {
 26702548            if (Attributes.Contains(d.Attributes, "_provided")) {
 2549              // Don't infer required-equality-support for the type parameters, since there are
 2550              // scopes that see the name of the declaration but not its body.
 26702551            } else if (d is DatatypeDecl) {
 02552              var dt = (DatatypeDecl)d;
 02553              foreach (var tp in dt.TypeArgs) {
 02554                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2555                  // here's our chance to infer the need for equality support
 02556                  foreach (var ctor in dt.Ctors) {
 02557                    foreach (var arg in ctor.Formals) {
 02558                      if (InferRequiredEqualitySupport(tp, arg.Type)) {
 02559                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02560                        inferredSomething = true;
 02561                        goto DONE_DT;  // break out of the doubly-nested loop
 2562                      }
 02563                    }
 02564                  }
 02565                DONE_DT:;
 02566                }
 02567              }
 35602568            } else if (d is TypeSynonymDecl) {
 8902569              var syn = (TypeSynonymDecl)d;
 40052570              foreach (var tp in syn.TypeArgs) {
 8902571                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2572                  // here's our chance to infer the need for equality support
 4452573                  if (InferRequiredEqualitySupport(tp, syn.Rhs)) {
 02574                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02575                    inferredSomething = true;
 02576                  }
 4452577                }
 4452578              }
 8902579            }
 26702580          }
 26702581        } while (inferredSomething);
 2582        // Now do it for Function and Method signatures.
 120152583        foreach (var d in declarations) {
 26702584          if (d is IteratorDecl) {
 02585            var iter = (IteratorDecl)d;
 02586            var done = false;
 02587            var nonnullIter = iter.NonNullTypeDecl;
 02588            Contract.Assert(nonnullIter.TypeArgs.Count == iter.TypeArgs.Count);
 02589            for (var i = 0; i < iter.TypeArgs.Count; i++) {
 02590              var tp = iter.TypeArgs[i];
 02591              var correspondingNonnullIterTypeParameter = nonnullIter.TypeArgs[i];
 02592              if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2593                // here's our chance to infer the need for equality support
 02594                foreach (var p in iter.Ins) {
 02595                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02596                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02597                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02598                    done = true;
 02599                    break;
 2600                  }
 02601                }
 02602                foreach (var p in iter.Outs) {
 02603                  if (done) {
 02604                    break;
 2605                  }
 2606
 02607                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02608                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02609                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02610                    break;
 2611                  }
 02612                }
 02613              }
 02614            }
 44502615          } else if (d is ClassDecl) {
 17802616            var cl = (ClassDecl)d;
 632252617            foreach (var member in cl.Members) {
 385902618              if (!member.IsGhost) {
 330052619                if (member is Function) {
 137102620                  var f = (Function)member;
 651602621                  foreach (var tp in f.TypeArgs) {
 160202622                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2623                      // here's our chance to infer the need for equality support
 80102624                      if (InferRequiredEqualitySupport(tp, f.ResultType)) {
 02625                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 80102626                      } else {
 934502627                        foreach (var p in f.Formals) {
 231402628                          if (InferRequiredEqualitySupport(tp, p.Type)) {
 02629                            tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02630                            break;
 2631                          }
 231402632                        }
 80102633                      }
 80102634                    }
 80102635                  }
 244352636                } else if (member is Method) {
 51402637                  var m = (Method)member;
 51402638                  bool done = false;
 154202639                  foreach (var tp in m.TypeArgs) {
 02640                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2641                      // here's our chance to infer the need for equality support
 02642                      foreach (var p in m.Ins) {
 02643                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02644                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02645                          done = true;
 02646                          break;
 2647                        }
 02648                      }
 02649                      foreach (var p in m.Outs) {
 02650                        if (done) {
 02651                          break;
 2652                        }
 2653
 02654                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02655                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02656                          break;
 2657                        }
 02658                      }
 02659                    }
 02660                  }
 51402661                }
 192952662              }
 192952663            }
 17802664          }
 26702665        }
 2666        // Check that functions claiming to be abstemious really are, and check that 'older' parameters are used only wh
 451352667        foreach (var fn in ModuleDefinition.AllFunctions(declarations)) {
 137102668          new Abstemious(reporter).Check(fn);
 137102669          CheckOlderParameters(fn);
 137102670        }
 2671        // Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2672        // Note that this check can only be done after determining which expressions are ghosts.
 120152673        foreach (var d in declarations) {
 106802674          for (var attr = d.Attributes; attr != null; attr = attr.Prev) {
 26702675            attr.Args.Iter(e => CheckTypeCharacteristics_Expr(e, true));
 17802676          }
 2677
 26702678          if (d is IteratorDecl) {
 02679            var iter = (IteratorDecl)d;
 02680            foreach (var p in iter.Ins) {
 02681              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02682            }
 02683            foreach (var p in iter.Outs) {
 02684              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02685            }
 02686            if (iter.Body != null) {
 02687              CheckTypeCharacteristics_Stmt(iter.Body, false);
 02688            }
 44502689          } else if (d is ClassDecl) {
 17802690            var cl = (ClassDecl)d;
 53402691            foreach (var parentTrait in cl.ParentTraits) {
 02692              CheckTypeCharacteristics_Type(cl.tok, parentTrait, false);
 02693            }
 26702694          } else if (d is DatatypeDecl) {
 02695            var dt = (DatatypeDecl)d;
 02696            foreach (var ctor in dt.Ctors) {
 02697              foreach (var p in ctor.Formals) {
 02698                CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02699              }
 02700            }
 17802701          } else if (d is TypeSynonymDecl) {
 8902702            var syn = (TypeSynonymDecl)d;
 8902703            CheckTypeCharacteristics_Type(syn.tok, syn.Rhs, false);
 17802704            if (!isAnExport) {
 8902705              if (syn.SupportsEquality && !syn.Rhs.SupportsEquality) {
 02706                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as supporting equality, but the RHS
 02707                  syn.Name, syn.Rhs);
 02708              }
 8902709              if (syn.Characteristics.IsNonempty && !syn.Rhs.IsNonempty) {
 02710                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as being nonempty, but the RHS type
 02711                  syn.Name, syn.Rhs);
 8902712              } else if (syn.Characteristics.HasCompiledValue && !syn.Rhs.HasCompilableValue) {
 02713                reporter.Error(MessageSource.Resolver, syn.tok,
 02714                  "type '{0}' declared as auto-initialization type, but the RHS type ({1}) does not support auto-initial
 02715              }
 8902716              if (syn.Characteristics.ContainsNoReferenceTypes && syn.Rhs.MayInvolveReferences) {
 02717                reporter.Error(MessageSource.Resolver, syn.tok,
 02718                  "type '{0}' declared as containing no reference types, but the RHS type ({1}) may contain reference ty
 02719              }
 8902720            }
 8902721          }
 2722
 35602723          if (d is RedirectingTypeDecl) {
 8902724            var rtd = (RedirectingTypeDecl)d;
 17802725            if (rtd.Constraint != null) {
 8902726              CheckTypeCharacteristics_Expr(rtd.Constraint, true);
 8902727            }
 8902728            if (rtd.Witness != null) {
 02729              CheckTypeCharacteristics_Expr(rtd.Witness, rtd.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 02730            }
 8902731          }
 2732
 44502733          if (d is TopLevelDeclWithMembers) {
 17802734            var cl = (TopLevelDeclWithMembers)d;
 632252735            foreach (var member in cl.Members) {
 197402736              if (member is Field) {
 4452737                var f = (Field)member;
 4452738                CheckTypeCharacteristics_Type(f.tok, f.Type, f.IsGhost);
 4452739                if (f is ConstantField cf && cf.Rhs != null) {
 02740                  CheckTypeCharacteristics_Expr(cf.Rhs, cf.IsGhost);
 02741                }
 330052742              } else if (member is Function) {
 137102743                var f = (Function)member;
 1463702744                foreach (var p in f.Formals) {
 350802745                  CheckTypeCharacteristics_Type(p.tok, p.Type, f.IsGhost || p.IsGhost);
 350802746                }
 274202747                if (f.Body != null) {
 137102748                  CheckTypeCharacteristics_Expr(f.Body, f.IsGhost);
 137102749                }
 239902750              } else if (member is Method) {
 51402751                var m = (Method)member;
 480302752                foreach (var p in m.Ins) {
 108702753                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 108702754                }
 345302755                foreach (var p in m.Outs) {
 63702756                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 63702757                }
 102802758                if (m.Body != null) {
 51402759                  CheckTypeCharacteristics_Stmt(m.Body, m.IsGhost);
 51402760                }
 51402761              }
 192952762            }
 17802763          }
 26702764        }
 2765        // Check that extreme predicates are not recursive with non-extreme-predicate functions (and only
 2766        // with extreme predicates of the same polarity), and
 2767        // check that greatest lemmas are not recursive with non-greatest-lemma methods.
 2768        // Also, check that the constraints of newtypes/subset-types do not depend on the type itself.
 2769        // And check that const initializers are not cyclic.
 13352770        var cycleErrorHasBeenReported = new HashSet<ICallable>();
 120152771        foreach (var d in declarations) {
 44502772          if (d is TopLevelDeclWithMembers { Members: var members }) {
 632252773            foreach (var member in members) {
 192952774              if (member is ExtremePredicate) {
 02775                var fn = (ExtremePredicate)member;
 2776                // Check here for the presence of any 'ensures' clauses, which are not allowed (because we're not sure
 2777                // of their soundness)
 02778                fn.Req.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02779                fn.Decreases.Expressions.ForEach(e => ExtremePredicateChecks(e, fn, CallingPosition.Positive));
 02780                fn.Reads.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02781                if (fn.Ens.Count != 0) {
 02782                  reporter.Error(MessageSource.Resolver, fn.Ens[0].E.tok, "a {0} is not allowed to declare any ensures c
 02783                }
 02784                if (fn.Body != null) {
 02785                  ExtremePredicateChecks(fn.Body, fn, CallingPosition.Positive);
 02786                }
 192952787              } else if (member is ExtremeLemma) {
 02788                var m = (ExtremeLemma)member;
 02789                m.Req.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02790                m.Ens.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02791                m.Decreases.Expressions.ForEach(e => ExtremeLemmaChecks(e, m));
 2792
 02793                if (m.Body != null) {
 02794                  ExtremeLemmaChecks(m.Body, m);
 02795                }
 192952796              } else if (member is ConstantField) {
 02797                var cf = (ConstantField)member;
 02798                if (cf.EnclosingModule.CallGraph.GetSCCSize(cf) != 1) {
 02799                  var r = cf.EnclosingModule.CallGraph.GetSCCRepresentative(cf);
 02800                  if (cycleErrorHasBeenReported.Contains(r)) {
 2801                    // An error has already been reported for this cycle, so don't report another.
 2802                    // Note, the representative, "r", may itself not be a const.
 02803                  } else {
 02804                    ReportCallGraphCycleError(cf, "const definition contains a cycle");
 02805                    cycleErrorHasBeenReported.Add(r);
 02806                  }
 02807                }
 02808              }
 192952809            }
 17802810          }
 2811
 35602812          if (d is RedirectingTypeDecl dd) {
 8902813            if (d.EnclosingModuleDefinition.CallGraph.GetSCCSize(dd) != 1) {
 02814              var r = d.EnclosingModuleDefinition.CallGraph.GetSCCRepresentative(dd);
 02815              if (cycleErrorHasBeenReported.Contains(r)) {
 2816                // An error has already been reported for this cycle, so don't report another.
 2817                // Note, the representative, "r", may itself not be a const.
 02818              } else if (dd is NewtypeDecl || dd is SubsetTypeDecl) {
 02819                ReportCallGraphCycleError(dd, $"recursive constraint dependency involving a {dd.WhatKind}");
 02820                cycleErrorHasBeenReported.Add(r);
 02821              }
 02822            }
 8902823          }
 26702824        }
 13352825      }
 2826
 2827      // ---------------------------------- Pass 3 ----------------------------------
 2828      // Further checks
 2829      // ----------------------------------------------------------------------------
 2830
 26702831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2832        // Check that type-parameter variance is respected in type definitions
 120152833        foreach (TopLevelDecl d in declarations) {
 44502834          if (d is IteratorDecl || d is ClassDecl) {
 66752835            foreach (var tp in d.TypeArgs) {
 4452836              if (tp.Variance != TypeParameter.TPVariance.Non) {
 02837                reporter.Error(MessageSource.Resolver, tp.tok, "{0} declarations only support non-variant type parameter
 02838              }
 4452839            }
 35602840          } else if (d is TypeSynonymDecl) {
 8902841            var dd = (TypeSynonymDecl)d;
 8902842            CheckVariance(dd.Rhs, dd, TypeParameter.TPVariance.Co, false);
 8902843          } else if (d is NewtypeDecl) {
 02844            var dd = (NewtypeDecl)d;
 02845            CheckVariance(dd.BaseType, dd, TypeParameter.TPVariance.Co, false);
 02846          } else if (d is DatatypeDecl) {
 02847            var dd = (DatatypeDecl)d;
 02848            foreach (var ctor in dd.Ctors) {
 02849              ctor.Formals.Iter(formal => CheckVariance(formal.Type, dd, TypeParameter.TPVariance.Co, false));
 02850            }
 02851          }
 26702852        }
 13352853      }
 2854
 26702855      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2856        // Check that usage of "this" is restricted before "new;" in constructor bodies,
 2857        // and that a class without any constructor only has fields with known initializers.
 2858        // Also check that static fields (which are necessarily const) have initializers.
 13352859        var cdci = new CheckDividedConstructorInit_Visitor(this);
 93452860        foreach (var cl in ModuleDefinition.AllTypesWithMembers(declarations)) {
 17802861          if (!(cl is ClassDecl)) {
 02862            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2863              // non-reference types (datatype, newtype, opaque) don't have constructors that can initialize fields
 02864              foreach (var member in cl.Members) {
 02865                if (member is ConstantField f && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02866                  CheckIsOkayWithoutRHS(f);
 02867                }
 02868              }
 02869            }
 02870            continue;
 2871          }
 22252872          if (cl is TraitDecl) {
 8902873            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2874              // traits never have constructors, but check for static consts
 13352875              foreach (var member in cl.Members) {
 02876                if (member is ConstantField f && f.IsStatic && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02877                  CheckIsOkayWithoutRHS(f);
 02878                }
 02879              }
 4452880            }
 4452881            continue;
 2882          }
 13352883          var hasConstructor = false;
 13352884          Field fieldWithoutKnownInitializer = null;
 618902885          foreach (var member in cl.Members) {
 192952886            if (member is Constructor) {
 02887              hasConstructor = true;
 02888              var constructor = (Constructor)member;
 02889              if (constructor.BodyInit != null) {
 02890                cdci.CheckInit(constructor.BodyInit);
 02891              }
 192952892            } else if (member is ConstantField && member.IsStatic) {
 02893              var f = (ConstantField)member;
 02894              if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract && f.Rhs == null && !f.IsExtern(Options, out _
 02895                CheckIsOkayWithoutRHS(f);
 02896              }
 197402897            } else if (member is Field && fieldWithoutKnownInitializer == null) {
 4452898              var f = (Field)member;
 4452899              if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2900                // fine
 4452901              } else if (!f.Type.KnownToHaveToAValue(f.IsGhost)) {
 02902                fieldWithoutKnownInitializer = f;
 02903              }
 4452904            }
 192952905          }
 26702906          if (!hasConstructor) {
 26702907            if (fieldWithoutKnownInitializer == null) {
 2908              // time to check inherited members
 40052909              foreach (var member in cl.InheritedMembers) {
 02910                if (member is Field) {
 02911                  var f = (Field)member;
 02912                  if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2913                    // fine
 02914                  } else if (!f.Type.Subst(cl.ParentFormalTypeParametersToActuals).KnownToHaveToAValue(f.IsGhost)) {
 02915                    fieldWithoutKnownInitializer = f;
 02916                    break;
 2917                  }
 02918                }
 02919              }
 13352920            }
 2921            // go through inherited members...
 13352922            if (fieldWithoutKnownInitializer != null) {
 02923              reporter.Error(MessageSource.Resolver, cl.tok, "class '{0}' with fields without known initializers, like '
 02924                cl.Name, fieldWithoutKnownInitializer.Name, fieldWithoutKnownInitializer.Type.Subst(cl.ParentFormalTypeP
 02925            }
 13352926          }
 13352927        }
 13352928      }
 2929      // Verifies that, in all compiled places, subset types in comprehensions have a compilable constraint
 13352930      new SubsetConstraintGhostChecker(this.Reporter).Traverse(declarations);
 13352931    }
 2932
 13352933    private void FillInPostConditionsAndBodiesOfPrefixLemmas(List<TopLevelDecl> declarations) {
 40052934      foreach (var com in ModuleDefinition.AllExtremeLemmas(declarations)) {
 02935        var prefixLemma = com.PrefixLemma;
 02936        if (prefixLemma == null) {
 02937          continue; // something went wrong during registration of the prefix lemma (probably a duplicated extreme lemma
 2938        }
 2939
 02940        var k = prefixLemma.Ins[0];
 02941        var focalPredicates = new HashSet<ExtremePredicate>();
 02942        if (com is GreatestLemma) {
 2943          // compute the postconditions of the prefix lemma
 02944          Contract.Assume(prefixLemma.Ens.Count == 0); // these are not supposed to have been filled in before
 02945          foreach (var p in com.Ens) {
 02946            var coConclusions = new HashSet<Expression>();
 02947            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, coConclusions, true, com);
 02948            var subst = new ExtremeLemmaSpecificationSubstituter(coConclusions, new IdentifierExpr(k.tok, k.Name),
 02949              this.reporter, true);
 02950            var post = subst.CloneExpr(p.E);
 02951            prefixLemma.Ens.Add(new AttributedExpression(post));
 02952            foreach (var e in coConclusions) {
 02953              var fce = e as FunctionCallExpr;
 02954              if (fce != null) {
 2955                // the other possibility is that "e" is a BinaryExpr
 02956                GreatestPredicate predicate = (GreatestPredicate)fce.Function;
 02957                focalPredicates.Add(predicate);
 2958                // For every focal predicate P in S, add to S all greatest predicates in the same strongly connected
 2959                // component (in the call graph) as P
 02960                foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(
 02961                           predicate)) {
 02962                  if (node is GreatestPredicate) {
 02963                    focalPredicates.Add((GreatestPredicate)node);
 02964                  }
 02965                }
 02966              }
 02967            }
 02968          }
 02969        } else {
 2970          // compute the preconditions of the prefix lemma
 02971          Contract.Assume(prefixLemma.Req.Count == 0); // these are not supposed to have been filled in before
 02972          foreach (var p in com.Req) {
 02973            var antecedents = new HashSet<Expression>();
 02974            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, antecedents, false, com);
 02975            var subst = new ExtremeLemmaSpecificationSubstituter(antecedents, new IdentifierExpr(k.tok, k.Name),
 02976              this.reporter, false);
 02977            var pre = subst.CloneExpr(p.E);
 02978            prefixLemma.Req.Add(new AttributedExpression(pre, p.Label, null));
 02979            foreach (var e in antecedents) {
 02980              var fce = (FunctionCallExpr)e; // we expect "antecedents" to contain only FunctionCallExpr's
 02981              LeastPredicate predicate = (LeastPredicate)fce.Function;
 02982              focalPredicates.Add(predicate);
 2983              // For every focal predicate P in S, add to S all least predicates in the same strongly connected
 2984              // component (in the call graph) as P
 02985              foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(predicate)) {
 02986                if (node is LeastPredicate) {
 02987                  focalPredicates.Add((LeastPredicate)node);
 02988                }
 02989              }
 02990            }
 02991          }
 02992        }
 2993
 02994        reporter.Info(MessageSource.Resolver, com.tok,
 02995          focalPredicates.Count == 0
 02996            ? $"{com.PrefixLemma.Name} has no focal predicates"
 02997            : $"{com.PrefixLemma.Name} with focal predicate{Util.Plural(focalPredicates.Count)} {Util.Comma(focalPredica
 2998        // Compute the statement body of the prefix lemma
 02999        Contract.Assume(prefixLemma.Body == null); // this is not supposed to have been filled in before
 03000        if (com.Body != null) {
 03001          var kMinusOne = new BinaryExpr(com.tok, BinaryExpr.Opcode.Sub, new IdentifierExpr(k.tok, k.Name),
 03002            new LiteralExpr(com.tok, 1));
 03003          var subst = new ExtremeLemmaBodyCloner(com, kMinusOne, focalPredicates, this.reporter);
 03004          var mainBody = subst.CloneBlockStmt(com.Body);
 3005          Expression kk;
 3006          Statement els;
 03007          if (k.Type.IsBigOrdinalType) {
 03008            kk = new MemberSelectExpr(k.tok, new IdentifierExpr(k.tok, k.Name), "Offset");
 3009            // As an "else" branch, we add recursive calls for the limit case.  When automatic induction is on,
 3010            // this get handled automatically, but we still want it in the case when automatic induction has been
 3011            // turned off.
 3012            //     forall k', params | k' < _k && Precondition {
 3013            //       pp(k', params);
 3014            //     }
 03015            Contract.Assume(builtIns.ORDINAL_Offset != null); // should have been filled in earlier
 03016            var kId = new IdentifierExpr(com.tok, k);
 03017            var kprimeVar = new BoundVar(com.tok, "_k'", Type.BigOrdinal);
 03018            var kprime = new IdentifierExpr(com.tok, kprimeVar);
 03019            var smaller = Expression.CreateLess(kprime, kId);
 3020
 03021            var bvs = new List<BoundVar>(); // the following loop populates bvs with k', params
 03022            var substMap = new Dictionary<IVariable, Expression>();
 03023            foreach (var inFormal in prefixLemma.Ins) {
 03024              if (inFormal == k) {
 03025                bvs.Add(kprimeVar);
 03026                substMap.Add(k, kprime);
 03027              } else {
 03028                var bv = new BoundVar(inFormal.tok, inFormal.Name, inFormal.Type);
 03029                bvs.Add(bv);
 03030                substMap.Add(inFormal, new IdentifierExpr(com.tok, bv));
 03031              }
 03032            }
 3033
 03034            Translator.RecursiveCallParameters(com.tok, prefixLemma, prefixLemma.TypeArgs, prefixLemma.Ins, null,
 03035              substMap, out var recursiveCallReceiver, out var recursiveCallArgs);
 03036            var methodSel = new MemberSelectExpr(com.tok, recursiveCallReceiver, prefixLemma.Name);
 03037            methodSel.Member = prefixLemma; // resolve here
 03038            methodSel.TypeApplication_AtEnclosingClass =
 03039              prefixLemma.EnclosingClass.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03040            methodSel.TypeApplication_JustMember =
 03041              prefixLemma.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03042            methodSel.Type = new InferredTypeProxy();
 03043            var recursiveCall = new CallStmt(com.RangeToken, new List<Expression>(), methodSel,
 03044              recursiveCallArgs.ConvertAll(e => new ActualBinding(null, e)));
 03045            recursiveCall.IsGhost = prefixLemma.IsGhost; // resolve here
 3046
 03047            var range = smaller; // The range will be strengthened later with the call's precondition, substituted
 3048            // appropriately (which can only be done once the precondition has been resolved).
 03049            var attrs = new Attributes("_autorequires", new List<Expression>(), null);
 3050#if VERIFY_CORRECTNESS_OF_TRANSLATION_FORALL_STATEMENT_RANGE
 3051              // don't add the :_trustWellformed attribute
 3052#else
 03053            attrs = new Attributes("_trustWellformed", new List<Expression>(), attrs);
 3054#endif
 03055            attrs = new Attributes("auto_generated", new List<Expression>(), attrs);
 03056            var forallBody = new BlockStmt(mainBody.RangeToken, new List<Statement>() { recursiveCall });
 03057            var forallStmt = new ForallStmt(mainBody.RangeToken, bvs, attrs, range,
 03058              new List<AttributedExpression>(), forallBody);
 03059            els = new BlockStmt(mainBody.RangeToken, new List<Statement>() { forallStmt });
 03060          } else {
 03061            kk = new IdentifierExpr(k.tok, k.Name);
 03062            els = null;
 03063          }
 3064
 03065          var kPositive = new BinaryExpr(com.tok, BinaryExpr.Opcode.Lt, new LiteralExpr(com.tok, 0), kk);
 03066          var condBody = new IfStmt(mainBody.RangeToken, false, kPositive, mainBody, els);
 03067          prefixLemma.Body = new BlockStmt(mainBody.RangeToken, new List<Statement>() { condBody });
 03068        }
 3069
 3070        // The prefix lemma now has all its components, so it's finally time we resolve it
 03071        currentClass = (TopLevelDeclWithMembers)prefixLemma.EnclosingClass;
 03072        allTypeParameters.PushMarker();
 03073        ResolveTypeParameters(currentClass.TypeArgs, false, currentClass);
 03074        ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03075        prefixLemma.Resolve(this);
 03076        allTypeParameters.PopMarker();
 03077        currentClass = null;
 03078        new CheckTypeInferenceVisitor(this).VisitMethod(prefixLemma);
 03079        CallGraphBuilder.VisitMethod(prefixLemma, reporter);
 03080        new BoundsDiscoveryVisitor(reporter).VisitMethod(prefixLemma);
 03081      }
 13353082    }
 3083
 03084    private void CheckIsOkayWithoutRHS(ConstantField f) {
 03085      if (f.IsGhost && !f.Type.IsNonempty) {
 03086        reporter.Error(MessageSource.Resolver, f.tok,
 03087          "{0}ghost const field '{1}' of type '{2}' (which may be empty) must give a defining value",
 03088          f.IsStatic ? "static " : "", f.Name, f.Type);
 03089      } else if (!f.IsGhost && !f.Type.HasCompilableValue) {
 03090        reporter.Error(MessageSource.Resolver, f.tok,
 03091          "{0}non-ghost const field '{1}' of type '{2}' (which does not have a default compiled value) must give a defin
 03092          f.IsStatic ? "static " : "", f.Name, f.Type);
 03093      }
 03094    }
 3095
 17803096    private void ResolveClassMembers_Pass1(TopLevelDeclWithMembers cl) {
 632253097      foreach (var member in cl.Members) {
 192953098        var prevErrCnt = reporter.Count(ErrorLevel.Error);
 385903099        if (prevErrCnt == reporter.Count(ErrorLevel.Error)) {
 244353100          if (member is Method method) {
 51403101            CheckForUnnecessaryEqualitySupportDeclarations(method, method.TypeArgs);
 51403102            CheckParameterDefaultValuesAreCompilable(method.Ins, method);
 102803103            if (method.Body != null) {
 51403104              ComputeGhostInterest(method.Body, method.IsGhost, method.IsLemmaLike ? "a " + method.WhatKind : null, meth
 51403105              CheckExpression(method.Body, this, method);
 51403106              new TailRecursion(reporter).DetermineTailRecursion(method);
 51403107            }
 3108
 330053109          } else if (member is Function function) {
 137103110            CheckForUnnecessaryEqualitySupportDeclarations(function, function.TypeArgs);
 137103111            CheckParameterDefaultValuesAreCompilable(function.Formals, function);
 274203112            if (function.ByMethodBody == null) {
 274203113              if (!function.IsGhost && function.Body != null) {
 137103114                ExpressionTester.CheckIsCompilable(Options, this, function.Body, function);
 137103115              }
 274203116              if (function.Body != null) {
 137103117                new TailRecursion(reporter).DetermineTailRecursion(function);
 137103118              }
 137103119            } else {
 03120              var m = function.ByMethodDecl;
 03121              if (m != null) {
 03122                Contract.Assert(!m.IsGhost);
 03123                ComputeGhostInterest(m.Body, false, null, m);
 03124                CheckExpression(m.Body, this, m);
 03125                new TailRecursion(reporter).DetermineTailRecursion(m);
 03126              } else {
 3127                // m should not be null, unless an error has been reported
 3128                // (e.g. function-by-method and method with the same name)
 03129                Contract.Assert(reporter.ErrorCount > 0);
 03130              }
 03131            }
 3132
 141553133          } else if (member is ConstantField field && field.Rhs != null && !field.IsGhost) {
 03134            ExpressionTester.CheckIsCompilable(Options, this, field.Rhs, field);
 03135          }
 3136
 381453137          if (prevErrCnt == reporter.Count(ErrorLevel.Error) && member is ICodeContext) {
 410603138            member.SubExpressions.Iter(e => CheckExpression(e, this, (ICodeContext)member));
 188503139          }
 192953140        }
 192953141      }
 17803142    }
 3143
 188503144    void CheckForUnnecessaryEqualitySupportDeclarations(MemberDecl member, List<TypeParameter> typeParameters) {
 188503145      if (member.IsGhost) {
 03146        foreach (var p in typeParameters.Where(p => p.SupportsEquality)) {
 03147          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, p.tok,
 03148            $"type parameter {p.Name} of ghost {member.WhatKind} {member.Name} is declared (==), which is unnecessary be
 03149        }
 03150      }
 188503151    }
 3152
 3153    /// <summary>
 3154    /// Check that default-value expressions are compilable, for non-ghost formals.
 3155    /// </summary>
 188503156    void CheckParameterDefaultValuesAreCompilable(List<Formal> formals, ICodeContext codeContext) {
 3157      Contract.Requires(formals != null);
 3158
 1025003159      foreach (var formal in formals.Where(f => f.DefaultValue != null)) {
 03160        if ((!codeContext.IsGhost || codeContext is DatatypeDecl) && !formal.IsGhost) {
 03161          ExpressionTester.CheckIsCompilable(Options, this, formal.DefaultValue, codeContext);
 03162        }
 03163        CheckExpression(formal.DefaultValue, this, codeContext);
 03164      }
 188503165    }
 3166
 03167    void ReportCallGraphCycleError(ICallable start, string msg) {
 3168      Contract.Requires(start != null);
 3169      Contract.Requires(msg != null);
 03170      var scc = start.EnclosingModule.CallGraph.GetSCC(start);
 03171      scc.Reverse();
 03172      var startIndex = scc.IndexOf(start);
 03173      Contract.Assert(0 <= startIndex);
 03174      scc = Util.Concat(scc.GetRange(startIndex, scc.Count - startIndex), scc.GetRange(0, startIndex));
 03175      ReportCycleError(scc, c => c.Tok, c => c.NameRelativeToModule, msg);
 03176    }
 3177
 03178    void ReportCycleError<X>(List<X> cycle, Func<X, IToken> toTok, Func<X, string> toString, string msg) {
 3179      Contract.Requires(cycle != null);
 3180      Contract.Requires(cycle.Count != 0);
 3181      Contract.Requires(toTok != null);
 3182      Contract.Requires(toString != null);
 3183      Contract.Requires(msg != null);
 3184
 03185      var start = cycle[0];
 03186      var cy = Util.Comma(" -> ", cycle, toString);
 03187      reporter.Error(MessageSource.Resolver, toTok(start), $"{msg}: {cy} -> {toString(start)}");
 03188    }
 3189
 3190    /// <summary>
 3191    /// Returns the largest value that can be stored in bitvector type "t".
 3192    /// </summary>
 03193    public static BigInteger MaxBV(Type t) {
 3194      Contract.Requires(t != null);
 3195      Contract.Requires(t.IsBitVectorType);
 03196      return MaxBV(t.AsBitVectorType.Width);
 03197    }
 3198
 3199    /// <summary>
 3200    /// Returns the largest value that can be stored in bitvector type of "bits" width.
 3201    /// </summary>
 03202    public static BigInteger MaxBV(int bits) {
 3203      Contract.Requires(0 <= bits);
 03204      return BigInteger.Pow(new BigInteger(2), bits) - BigInteger.One;
 03205    }
 3206
 03207    private void FigureOutNativeType(NewtypeDecl dd) {
 3208      Contract.Requires(dd != null);
 3209
 3210      // Look at the :nativeType attribute, if any
 3211      bool mustUseNativeType;
 03212      List<NativeType> nativeTypeChoices = null;  // null means "no preference"
 03213      var args = Attributes.FindExpressions(dd.Attributes, "nativeType");
 03214      if (args != null && !dd.BaseType.IsNumericBased(Type.NumericPersuasion.Int)) {
 03215        reporter.Error(MessageSource.Resolver, dd, ":nativeType can only be used on integral types");
 03216        return;
 03217      } else if (args == null) {
 3218        // There was no :nativeType attribute
 03219        mustUseNativeType = false;
 03220      } else if (args.Count == 0) {
 03221        mustUseNativeType = true;
 03222      } else {
 03223        var arg0Lit = args[0] as LiteralExpr;
 03224        if (arg0Lit != null && arg0Lit.Value is bool) {
 03225          if (!(bool)arg0Lit.Value) {
 3226            // {:nativeType false} says "don't use native type", so our work here is done
 03227            return;
 3228          }
 03229          mustUseNativeType = true;
 03230        } else {
 03231          mustUseNativeType = true;
 03232          nativeTypeChoices = new List<NativeType>();
 03233          foreach (var arg in args) {
 03234            if (arg is LiteralExpr lit && lit.Value is string s) {
 3235              // Get the NativeType for "s"
 03236              foreach (var nativeT in NativeTypes) {
 03237                if (nativeT.Name == s) {
 03238                  nativeTypeChoices.Add(nativeT);
 03239                  goto FoundNativeType;
 3240                }
 03241              }
 03242              reporter.Error(MessageSource.Resolver, dd, ":nativeType '{0}' not known", s);
 03243              return;
 03244            FoundNativeType:;
 03245            } else {
 03246              reporter.Error(MessageSource.Resolver, arg, "unexpected :nativeType argument");
 03247              return;
 3248            }
 03249          }
 03250        }
 03251      }
 3252
 3253      // Figure out the variable and constraint.  Usually, these would be just .Var and .Constraint, but
 3254      // in the case .Var is null, these can be computed from the .BaseType recursively.
 03255      var ddVar = dd.Var;
 03256      var ddConstraint = dd.Constraint;
 03257      for (var ddWhereConstraintsAre = dd; ddVar == null;) {
 03258        ddWhereConstraintsAre = ddWhereConstraintsAre.BaseType.AsNewtype;
 03259        if (ddWhereConstraintsAre == null) {
 03260          break;
 3261        }
 03262        ddVar = ddWhereConstraintsAre.Var;
 03263        ddConstraint = ddWhereConstraintsAre.Constraint;
 03264      }
 3265      List<ComprehensionExpr.BoundedPool> bounds;
 03266      if (ddVar == null) {
 3267        // There are no bounds at all
 03268        bounds = new List<ComprehensionExpr.BoundedPool>();
 03269      } else {
 03270        bounds = DiscoverAllBounds_SingleVar(ddVar, ddConstraint);
 03271      }
 3272
 3273      // Returns null if the argument is a constrained newtype (recursively)
 3274      // Returns the transitive base type if the argument is recusively unconstrained
 03275      Type AsUnconstrainedType(Type t) {
 03276        while (true) {
 03277          if (t.AsNewtype == null) {
 03278            return t;
 3279          }
 3280
 03281          if (t.AsNewtype.Constraint != null) {
 03282            return null;
 3283          }
 3284
 03285          t = t.AsNewtype.BaseType;
 03286        }
 03287      }
 3288
 3289      // Find which among the allowable native types can hold "dd". Give an
 3290      // error for any user-specified native type that's not big enough.
 03291      var bigEnoughNativeTypes = new List<NativeType>();
 3292      // But first, define a local, recursive function GetConst/GetAnyConst:
 3293      // These fold any constant computations, including symbolic constants,
 3294      // returning null if folding is not possible. If an operation is undefined
 3295      // (divide by zero, conversion out of range, etc.), then null is returned.
 03296      Func<Expression, BigInteger?> GetConst = null;
 03297      Func<Expression, Stack<ConstantField>, Object> GetAnyConst = null;
 03298      GetAnyConst = (Expression e, Stack<ConstantField> consts) => {
 03299        if (e is LiteralExpr l) {
 03300          return l.Value;
 03301        } else if (e is UnaryOpExpr un) {
 03302          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot && GetAnyConst(un.E, consts) is bool b) {
 03303            return !b;
 03304          }
 03305          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BVNot && GetAnyConst(un.E, consts) is BigInteger i) {
 03306            return ((BigInteger.One << un.Type.AsBitVectorType.Width) - 1) ^ i;
 03307          }
 03308          // TODO: This only handles strings; generalize to other collections?
 03309          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.SeqLength && GetAnyConst(un.E, consts) is string ss) {
 03310            return (BigInteger)(ss.Length);
 03311          }
 03312        } else if (e is MemberSelectExpr m) {
 03313          if (m.Member is ConstantField c && c.IsStatic && c.Rhs != null) {
 03314            // This aspect of type resolution happens before the check for cyclic references
 03315            // so we have to do a check here as well. If cyclic, null is silently returned,
 03316            // counting on the later error message to alert the user.
 03317            if (consts.Contains(c)) { return null; }
 03318            consts.Push(c);
 03319            Object o = GetAnyConst(c.Rhs, consts);
 03320            consts.Pop();
 03321            return o;
 03322          } else if (m.Member is SpecialField sf) {
 03323            string nm = sf.Name;
 03324            if (nm == "Floor") {
 03325              Object ee = GetAnyConst(m.Obj, consts);
 03326              if (ee != null && m.Obj.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03327                ((BaseTypes.BigDec)ee).FloorCeiling(out var f, out _);
 03328                return f;
 03329              }
 03330            }
 03331          }
 03332        } else if (e is BinaryExpr bin) {
 03333          Object e0 = GetAnyConst(bin.E0, consts);
 03334          Object e1 = GetAnyConst(bin.E1, consts);
 03335          bool isBool = bin.E0.Type == Type.Bool && bin.E1.Type == Type.Bool;
 03336          bool shortCircuit = isBool && (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.And
 03337                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Or
 03338                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Imp);
 03339
 03340          if (e0 == null || (!shortCircuit && e1 == null)) { return null; }
 03341          bool isAnyReal = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)
 03342                        && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Real);
 03343          bool isAnyInt = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Int)
 03344                       && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Int);
 03345          bool isReal = bin.Type.IsRealType;
 03346          bool isInt = bin.Type.IsIntegerType;
 03347          bool isBV = bin.E0.Type.IsBitVectorType;
 03348          int width = isBV ? bin.E0.Type.AsBitVectorType.Width : 0;
 03349          bool isString = e0 is string && e1 is string;
 03350          switch (bin.ResolvedOp) {
 03351            case BinaryExpr.ResolvedOpcode.Add:
 03352              if (isInt) {
 03353                return (BigInteger)e0 + (BigInteger)e1;
 03354              }
 03355
 03356              if (isBV) {
 03357                return ((BigInteger)e0 + (BigInteger)e1) & MaxBV(bin.Type);
 03358              }
 03359
 03360              if (isReal) {
 03361                return (BaseTypes.BigDec)e0 + (BaseTypes.BigDec)e1;
 03362              }
 03363
 03364              break;
 03365            case BinaryExpr.ResolvedOpcode.Concat:
 03366              if (isString) {
 03367                return (string)e0 + (string)e1;
 03368              }
 03369
 03370              break;
 03371            case BinaryExpr.ResolvedOpcode.Sub:
 03372              if (isInt) {
 03373                return (BigInteger)e0 - (BigInteger)e1;
 03374              }
 03375
 03376              if (isBV) {
 03377                return ((BigInteger)e0 - (BigInteger)e1) & MaxBV(bin.Type);
 03378              }
 03379
 03380              if (isReal) {
 03381                return (BaseTypes.BigDec)e0 - (BaseTypes.BigDec)e1;
 03382              }
 03383              // Allow a special case: If the result type is a newtype that is integer-based (i.e., isInt && !isInteger)
 03384              // then we generally do not fold the operations, because we do not determine whether the
 03385              // result of the operation satisfies the new type constraint. However, on the occasion that
 03386              // a newtype aliases int without a constraint, it occurs that a value of the newtype is initialized
 03387              // with a negative value, which is represented as "0 - N", that is, it comes to this case. It
 03388              // is a nuisance not to constant-fold the result, as not doing so can alter the determination
 03389              // of the representation type.
 03390              if (isAnyInt && AsUnconstrainedType(bin.Type) != null) {
 03391                return ((BigInteger)e0) - ((BigInteger)e1);
 03392              }
 03393              break;
 03394            case BinaryExpr.ResolvedOpcode.Mul:
 03395              if (isInt) {
 03396                return (BigInteger)e0 * (BigInteger)e1;
 03397              }
 03398
 03399              if (isBV) {
 03400                return ((BigInteger)e0 * (BigInteger)e1) & MaxBV(bin.Type);
 03401              }
 03402
 03403              if (isReal) {
 03404                return (BaseTypes.BigDec)e0 * (BaseTypes.BigDec)e1;
 03405              }
 03406
 03407              break;
 03408            case BinaryExpr.ResolvedOpcode.BitwiseAnd:
 03409              Contract.Assert(isBV);
 03410              return (BigInteger)e0 & (BigInteger)e1;
 03411            case BinaryExpr.ResolvedOpcode.BitwiseOr:
 03412              Contract.Assert(isBV);
 03413              return (BigInteger)e0 | (BigInteger)e1;
 03414            case BinaryExpr.ResolvedOpcode.BitwiseXor:
 03415              Contract.Assert(isBV);
 03416              return (BigInteger)e0 ^ (BigInteger)e1;
 03417            case BinaryExpr.ResolvedOpcode.Div:
 03418              if (isInt) {
 03419                if ((BigInteger)e1 == 0) {
 03420                  return null; // Divide by zero
 03421                } else {
 03422                  BigInteger a0 = (BigInteger)e0;
 03423                  BigInteger a1 = (BigInteger)e1;
 03424                  BigInteger d = a0 / a1;
 03425                  return a0 >= 0 || a0 == d * a1 ? d : a1 > 0 ? d - 1 : d + 1;
 03426                }
 03427              }
 03428              if (isBV) {
 03429                if ((BigInteger)e1 == 0) {
 03430                  return null; // Divide by zero
 03431                } else {
 03432                  return ((BigInteger)e0) / ((BigInteger)e1);
 03433                }
 03434              }
 03435              if (isReal) {
 03436                if ((BaseTypes.BigDec)e1 == BaseTypes.BigDec.ZERO) {
 03437                  return null; // Divide by zero
 03438                } else {
 03439                  // BigDec does not have divide and is not a representation of rationals, so we don't do constant foldi
 03440                  return null;
 03441                }
 03442              }
 03443
 03444              break;
 03445            case BinaryExpr.ResolvedOpcode.Mod:
 03446              if (isInt) {
 03447                if ((BigInteger)e1 == 0) {
 03448                  return null; // Mod by zero
 03449                } else {
 03450                  BigInteger a = BigInteger.Abs((BigInteger)e1);
 03451                  BigInteger d = (BigInteger)e0 % a;
 03452                  return (BigInteger)e0 >= 0 ? d : d + a;
 03453                }
 03454              }
 03455              if (isBV) {
 03456                if ((BigInteger)e1 == 0) {
 03457                  return null; // Mod by zero
 03458                } else {
 03459                  return (BigInteger)e0 % (BigInteger)e1;
 03460                }
 03461              }
 03462              break;
 03463            case BinaryExpr.ResolvedOpcode.LeftShift: {
 03464                if ((BigInteger)e1 < 0) {
 03465                  return null; // Negative shift
 03466                }
 03467                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03468                  return null; // Shift is too large
 03469                }
 03470                return ((BigInteger)e0 << (int)(BigInteger)e1) & MaxBV(bin.E0.Type);
 03471              }
 03472            case BinaryExpr.ResolvedOpcode.RightShift: {
 03473                if ((BigInteger)e1 < 0) {
 03474                  return null; // Negative shift
 03475                }
 03476                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03477                  return null; // Shift too large
 03478                }
 03479                return (BigInteger)e0 >> (int)(BigInteger)e1;
 03480              }
 03481            case BinaryExpr.ResolvedOpcode.And: {
 03482                if ((bool)e0 && e1 == null) {
 03483                  return null;
 03484                }
 03485
 03486                return (bool)e0 && (bool)e1;
 03487              }
 03488            case BinaryExpr.ResolvedOpcode.Or: {
 03489                if (!(bool)e0 && e1 == null) {
 03490                  return null;
 03491                }
 03492
 03493                return (bool)e0 || (bool)e1;
 03494              }
 03495            case BinaryExpr.ResolvedOpcode.Imp: { // ==> and <==
 03496                if ((bool)e0 && e1 == null) {
 03497                  return null;
 03498                }
 03499
 03500                return !(bool)e0 || (bool)e1;
 03501              }
 03502            case BinaryExpr.ResolvedOpcode.Iff: return (bool)e0 == (bool)e1; // <==>
 03503            case BinaryExpr.ResolvedOpcode.Gt:
 03504              if (isAnyInt) {
 03505                return (BigInteger)e0 > (BigInteger)e1;
 03506              }
 03507
 03508              if (isBV) {
 03509                return (BigInteger)e0 > (BigInteger)e1;
 03510              }
 03511
 03512              if (isAnyReal) {
 03513                return (BaseTypes.BigDec)e0 > (BaseTypes.BigDec)e1;
 03514              }
 03515
 03516              break;
 03517            case BinaryExpr.ResolvedOpcode.GtChar:
 03518              if (bin.E0.Type.IsCharType) {
 03519                return ((string)e0)[0] > ((string)e1)[0];
 03520              }
 03521
 03522              break;
 03523            case BinaryExpr.ResolvedOpcode.Ge:
 03524              if (isAnyInt) {
 03525                return (BigInteger)e0 >= (BigInteger)e1;
 03526              }
 03527
 03528              if (isBV) {
 03529                return (BigInteger)e0 >= (BigInteger)e1;
 03530              }
 03531
 03532              if (isAnyReal) {
 03533                return (BaseTypes.BigDec)e0 >= (BaseTypes.BigDec)e1;
 03534              }
 03535
 03536              break;
 03537            case BinaryExpr.ResolvedOpcode.GeChar:
 03538              if (bin.E0.Type.IsCharType) {
 03539                return ((string)e0)[0] >= ((string)e1)[0];
 03540              }
 03541
 03542              break;
 03543            case BinaryExpr.ResolvedOpcode.Lt:
 03544              if (isAnyInt) {
 03545                return (BigInteger)e0 < (BigInteger)e1;
 03546              }
 03547
 03548              if (isBV) {
 03549                return (BigInteger)e0 < (BigInteger)e1;
 03550              }
 03551
 03552              if (isAnyReal) {
 03553                return (BaseTypes.BigDec)e0 < (BaseTypes.BigDec)e1;
 03554              }
 03555
 03556              break;
 03557            case BinaryExpr.ResolvedOpcode.LtChar:
 03558              if (bin.E0.Type.IsCharType) {
 03559                return ((string)e0)[0] < ((string)e1)[0];
 03560              }
 03561
 03562              break;
 03563            case BinaryExpr.ResolvedOpcode.ProperPrefix:
 03564              if (isString) {
 03565                return ((string)e1).StartsWith((string)e0) && !((string)e1).Equals((string)e0);
 03566              }
 03567
 03568              break;
 03569            case BinaryExpr.ResolvedOpcode.Le:
 03570              if (isAnyInt) {
 03571                return (BigInteger)e0 <= (BigInteger)e1;
 03572              }
 03573
 03574              if (isBV) {
 03575                return (BigInteger)e0 <= (BigInteger)e1;
 03576              }
 03577
 03578              if (isAnyReal) {
 03579                return (BaseTypes.BigDec)e0 <= (BaseTypes.BigDec)e1;
 03580              }
 03581
 03582              break;
 03583            case BinaryExpr.ResolvedOpcode.LeChar:
 03584              if (bin.E0.Type.IsCharType) {
 03585                return ((string)e0)[0] <= ((string)e1)[0];
 03586              }
 03587
 03588              break;
 03589            case BinaryExpr.ResolvedOpcode.Prefix:
 03590              if (isString) {
 03591                return ((string)e1).StartsWith((string)e0);
 03592              }
 03593
 03594              break;
 03595            case BinaryExpr.ResolvedOpcode.EqCommon: {
 03596                if (isBool) {
 03597                  return (bool)e0 == (bool)e1;
 03598                } else if (isAnyInt || isBV) {
 03599                  return (BigInteger)e0 == (BigInteger)e1;
 03600                } else if (isAnyReal) {
 03601                  return (BaseTypes.BigDec)e0 == (BaseTypes.BigDec)e1;
 03602                } else if (bin.E0.Type.IsCharType) {
 03603                  return ((string)e0)[0] == ((string)e1)[0];
 03604                }
 03605                break;
 03606              }
 03607            case BinaryExpr.ResolvedOpcode.SeqEq:
 03608              if (isString) {
 03609                return (string)e0 == (string)e1;
 03610              }
 03611              break;
 03612            case BinaryExpr.ResolvedOpcode.SeqNeq:
 03613              if (isString) {
 03614                return (string)e0 != (string)e1;
 03615              }
 03616              break;
 03617            case BinaryExpr.ResolvedOpcode.NeqCommon: {
 03618                if (isBool) {
 03619                  return (bool)e0 != (bool)e1;
 03620                } else if (isAnyInt || isBV) {
 03621                  return (BigInteger)e0 != (BigInteger)e1;
 03622                } else if (isAnyReal) {
 03623                  return (BaseTypes.BigDec)e0 != (BaseTypes.BigDec)e1;
 03624                } else if (bin.E0.Type.IsCharType) {
 03625                  return ((string)e0)[0] != ((string)e1)[0];
 03626                } else if (isString) {
 03627                  return (string)e0 != (string)e1;
 03628                }
 03629                break;
 03630              }
 03631          }
 03632        } else if (e is ConversionExpr ce) {
 03633          object o = GetAnyConst(ce.E, consts);
 03634          if (o == null || ce.E.Type == ce.Type) {
 03635            return o;
 03636          }
 03637
 03638          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03639                ce.Type.IsBitVectorType) {
 03640            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03641            if (ff < 0 || ff > MaxBV(ce.Type)) {
 03642              return null; // Out of range
 03643            }
 03644            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03645              return null; // Out of range
 03646            }
 03647            return ff;
 03648          }
 03649
 03650          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03651                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03652            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03653            if (AsUnconstrainedType(ce.Type) == null) {
 03654              return null;
 03655            }
 03656
 03657            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03658              return null; // Argument not an integer
 03659            }
 03660            return ff;
 03661          }
 03662
 03663          if (ce.E.Type.IsBitVectorType &&
 03664                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03665            if (AsUnconstrainedType(ce.Type) == null) {
 03666              return null;
 03667            }
 03668
 03669            return o;
 03670          }
 03671
 03672          if (ce.E.Type.IsBitVectorType &&
 03673                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03674            if (AsUnconstrainedType(ce.Type) == null) {
 03675              return null;
 03676            }
 03677
 03678            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03679          }
 03680
 03681          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03682                ce.Type.IsBitVectorType) {
 03683            BigInteger b = (BigInteger)o;
 03684            if (b < 0 || b > MaxBV(ce.Type)) {
 03685              return null; // Argument out of range
 03686            }
 03687            return o;
 03688          }
 03689
 03690          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03691                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03692            // This case includes int-based newtypes to int-based new types
 03693            if (AsUnconstrainedType(ce.Type) == null) {
 03694              return null;
 03695            }
 03696
 03697            return o;
 03698          }
 03699
 03700          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03701                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03702            // This case includes real-based newtypes to real-based new types
 03703            if (AsUnconstrainedType(ce.Type) == null) {
 03704              return null;
 03705            }
 03706
 03707            return o;
 03708          }
 03709
 03710          if (ce.E.Type.IsBitVectorType && ce.Type.IsBitVectorType) {
 03711            BigInteger b = (BigInteger)o;
 03712            if (b < 0 || b > MaxBV(ce.Type)) {
 03713              return null; // Argument out of range
 03714            }
 03715            return o;
 03716          }
 03717
 03718          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03719                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03720            if (AsUnconstrainedType(ce.Type) == null) {
 03721              return null;
 03722            }
 03723
 03724            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03725          }
 03726
 03727          if (ce.E.Type.IsCharType && ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03728            char c = ((String)o)[0];
 03729            if (AsUnconstrainedType(ce.Type) == null) {
 03730              return null;
 03731            }
 03732
 03733            return new BigInteger(((string)o)[0]);
 03734          }
 03735
 03736          if (ce.E.Type.IsCharType && ce.Type.IsBitVectorType) {
 03737            char c = ((String)o)[0];
 03738            if ((int)c > MaxBV(ce.Type)) {
 03739              return null; // Argument out of range
 03740            }
 03741            return new BigInteger(((string)o)[0]);
 03742          }
 03743
 03744          if ((ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || ce.E.Type.IsBitVectorType) &&
 03745                ce.Type.IsCharType) {
 03746            BigInteger b = (BigInteger)o;
 03747            if (b < BigInteger.Zero || b > new BigInteger(65535)) {
 03748              return null; // Argument out of range
 03749            }
 03750            return ((char)(int)b).ToString();
 03751          }
 03752
 03753          if (ce.E.Type.IsCharType &&
 03754              ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03755            if (AsUnconstrainedType(ce.Type) == null) {
 03756              return null;
 03757            }
 03758
 03759            return BaseTypes.BigDec.FromInt(((string)o)[0]);
 03760          }
 03761
 03762          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03763                ce.Type.IsCharType) {
 03764            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03765            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03766              return null; // Argument not an integer
 03767            }
 03768            if (ff < BigInteger.Zero || ff > new BigInteger(65535)) {
 03769              return null; // Argument out of range
 03770            }
 03771            return ((char)(int)ff).ToString();
 03772          }
 03773
 03774        } else if (e is SeqSelectExpr sse) {
 03775          var b = GetAnyConst(sse.Seq, consts) as string;
 03776          BigInteger index = (BigInteger)GetAnyConst(sse.E0, consts);
 03777          if (b == null) {
 03778            return null;
 03779          }
 03780
 03781          if (index < 0 || index >= b.Length || index > Int32.MaxValue) {
 03782            return null; // Index out of range
 03783          }
 03784          return b[(int)index].ToString();
 03785        } else if (e is ITEExpr ite) {
 03786          Object b = GetAnyConst(ite.Test, consts);
 03787          if (b == null) {
 03788            return null;
 03789          }
 03790
 03791          return ((bool)b) ? GetAnyConst(ite.Thn, consts) : GetAnyConst(ite.Els, consts);
 03792        } else if (e is ConcreteSyntaxExpression n) {
 03793          return GetAnyConst(n.ResolvedExpression, consts);
 03794        } else {
 03795          return null;
 03796        }
 03797        return null;
 03798      };
 03799      GetConst = (Expression e) => {
 03800        Object ee = GetAnyConst(e.Resolved ?? e, new Stack<ConstantField>());
 03801        return ee as BigInteger?;
 03802      };
 3803      // Now, then, let's go through them types.
 3804      // FIXME - should first go through the bounds to find the most constraining values
 3805      // then check those values against the possible types. Note that also presumes the types are in order.
 03806      BigInteger? lowest = null;
 03807      BigInteger? highest = null;
 03808      foreach (var bound in bounds) {
 03809        if (bound is ComprehensionExpr.IntBoundedPool) {
 03810          var bnd = (ComprehensionExpr.IntBoundedPool)bound;
 03811          if (bnd.LowerBound != null) {
 03812            BigInteger? lower = GetConst(bnd.LowerBound);
 03813            if (lower != null && (lowest == null || lower < lowest)) {
 03814              lowest = lower;
 03815            }
 03816          }
 03817          if (bnd.UpperBound != null) {
 03818            BigInteger? upper = GetConst(bnd.UpperBound);
 03819            if (upper != null && (highest == null || upper > highest)) {
 03820              highest = upper;
 03821            }
 03822          }
 03823        }
 03824      }
 03825      foreach (var nativeT in nativeTypeChoices ?? NativeTypes) {
 03826        bool lowerOk = (lowest != null && nativeT.LowerBound <= lowest);
 03827        bool upperOk = (highest != null && nativeT.UpperBound >= highest);
 03828        if (lowerOk && upperOk) {
 03829          bigEnoughNativeTypes.Add(nativeT);
 03830        } else if (nativeTypeChoices != null) {
 03831          reporter.Error(MessageSource.Resolver, dd,
 03832            "Dafny's heuristics failed to confirm '{0}' to be a compatible native type.  " +
 03833            "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additio
 03834            nativeT.Name);
 03835          return;
 3836        }
 03837      }
 3838
 3839      // Finally, of the big-enough native types, pick the first one that is
 3840      // supported by the selected target compiler.
 03841      foreach (var nativeT in bigEnoughNativeTypes) {
 03842        if (Options.Backend.SupportedNativeTypes.Contains(nativeT.Name)) {
 03843          dd.NativeType = nativeT;
 03844          break;
 3845        }
 03846      }
 03847      if (dd.NativeType != null) {
 3848        // Give an info message saying which type was selected--unless the user requested
 3849        // one particular native type, in which case that must have been the one picked.
 03850        if (nativeTypeChoices != null && nativeTypeChoices.Count == 1) {
 03851          Contract.Assert(dd.NativeType == nativeTypeChoices[0]);
 03852        } else {
 03853          reporter.Info(MessageSource.Resolver, dd.tok, "newtype " + dd.Name + " resolves as {:nativeType \"" + dd.Nativ
 03854        }
 03855      } else if (nativeTypeChoices != null) {
 03856        reporter.Error(MessageSource.Resolver, dd,
 03857          "None of the types given in :nativeType arguments is supported by the current compilation target. Try supplyin
 03858      } else if (mustUseNativeType) {
 03859        reporter.Error(MessageSource.Resolver, dd,
 03860          "Dafny's heuristics cannot find a compatible native type.  " +
 03861          "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additiona
 03862      }
 03863    }
 3864
 3865    /// <summary>
 3866    /// Check that the 'older' modifier on parameters is used correctly and report any errors of the contrary.
 3867    /// </summary>
 137103868    void CheckOlderParameters(Function f) {
 3869      Contract.Requires(f != null);
 3870
 271603871      if (!f.ResultType.IsBoolType || f is PrefixPredicate || f is ExtremePredicate) {
 3872        // parameters are not allowed to be marked 'older'
 1431903873        foreach (var formal in f.Formals) {
 342803874          if (formal.IsOlder) {
 03875            reporter.Error(MessageSource.Resolver, formal.tok, "only predicates and two-state predicates are allowed 'ol
 03876          }
 342803877        }
 134503878      }
 137103879    }
 3880
 3881    // ------------------------------------------------------------------------------------------------------
 3882    // ----- CheckExpression --------------------------------------------------------------------------------
 3883    // ------------------------------------------------------------------------------------------------------
 3884    #region CheckExpression
 3885    /// <summary>
 3886    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3887    /// checks for hint restrictions in any CalcStmt.
 3888    /// </summary>
 231003889    void CheckExpression(Expression expr, Resolver resolver, ICodeContext codeContext) {
 3890      Contract.Requires(expr != null);
 3891      Contract.Requires(resolver != null);
 3892      Contract.Requires(codeContext != null);
 231003893      var v = new CheckExpression_Visitor(resolver, codeContext);
 231003894      v.Visit(expr);
 231003895    }
 3896    /// <summary>
 3897    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3898    /// checks for hint restrictions in any CalcStmt. In any ghost context, it also
 3899    /// changes the bound variables of all let- and let-such-that expressions to ghost.
 3900    /// It also performs substitutions in DefaultValueExpression's.
 3901    /// </summary>
 51403902    void CheckExpression(Statement stmt, Resolver resolver, ICodeContext codeContext) {
 3903      Contract.Requires(stmt != null);
 3904      Contract.Requires(resolver != null);
 3905      Contract.Requires(codeContext != null);
 51403906      var v = new CheckExpression_Visitor(resolver, codeContext);
 51403907      v.Visit(stmt);
 51403908    }
 3909    class CheckExpression_Visitor : ResolverBottomUpVisitor {
 3910      readonly ICodeContext CodeContext;
 3911      public CheckExpression_Visitor(Resolver resolver, ICodeContext codeContext)
 564803912        : base(resolver) {
 3913        Contract.Requires(resolver != null);
 3914        Contract.Requires(codeContext != null);
 282403915        CodeContext = codeContext;
 282403916      }
 27665403917      protected override void VisitOneExpr(Expression expr) {
 27665403918        if (expr is StmtExpr) {
 03919          var e = (StmtExpr)expr;
 03920          resolver.ComputeGhostInterest(e.S, true, "a statement expression", CodeContext);
 28030403921        } else if (expr is LetExpr) {
 365003922          var e = (LetExpr)expr;
 365003923          if (CodeContext.IsGhost) {
 03924            foreach (var bv in e.BoundVars) {
 03925              bv.MakeGhost();
 03926            }
 03927          }
 365003928        }
 27665403929      }
 3930
 11973203931      protected override void VisitOneStmt(Statement stmt) {
 11973203932        if (stmt is CalcStmt calc) {
 03933          foreach (var h in calc.Hints) {
 03934            resolver.CheckLocalityUpdates(h, new HashSet<LocalVariable>(), "a hint");
 03935          }
 11973203936        } else if (stmt is AssertStmt astmt && astmt.Proof != null) {
 03937          resolver.CheckLocalityUpdates(astmt.Proof, new HashSet<LocalVariable>(), "an assert-by body");
 11973203938        } else if (stmt is ForallStmt forall && forall.Body != null) {
 03939          resolver.CheckLocalityUpdates(forall.Body, new HashSet<LocalVariable>(), "a forall statement");
 03940        }
 11973203941      }
 3942    }
 3943    #endregion
 3944
 3945    // ------------------------------------------------------------------------------------------------------
 3946    // ----- FuelAdjustmentChecks ---------------------------------------------------------------------------
 3947    // ------------------------------------------------------------------------------------------------------
 3948    #region FuelAdjustmentChecks
 3949
 6085303950    protected void CheckForFuelAdjustments(IToken tok, Attributes attrs, ModuleDefinition currentModule) {
 6085303951      List<List<Expression>> results = Attributes.FindAllExpressions(attrs, "fuel");
 3952
 6085303953      if (results != null) {
 03954        foreach (List<Expression> args in results) {
 03955          if (args != null && args.Count >= 2) {
 3956            // Try to extract the function from the first argument
 03957            MemberSelectExpr selectExpr = args[0].Resolved as MemberSelectExpr;
 03958            if (selectExpr != null) {
 03959              Function f = selectExpr.Member as Function;
 03960              if (f != null) {
 03961                f.IsFueled = true;
 03962                if (args.Count >= 3) {
 03963                  LiteralExpr literalLow = args[1] as LiteralExpr;
 03964                  LiteralExpr literalHigh = args[2] as LiteralExpr;
 03965                  if (literalLow != null && literalLow.Value is BigInteger && literalHigh != null && literalHigh.Value i
 03966                    BigInteger low = (BigInteger)literalLow.Value;
 03967                    BigInteger high = (BigInteger)literalHigh.Value;
 03968                    if (!(high == low + 1 || (low == 0 && high == 0))) {
 03969                      reporter.Error(MessageSource.Resolver, tok, "fuel setting for function {0} must have high value ==
 03970                    }
 03971                  }
 03972                }
 03973              }
 03974            }
 03975          }
 03976        }
 03977      }
 6085303978    }
 3979
 3980    public class FuelAdjustment_Context {
 3981      public ModuleDefinition currentModule;
 188503982      public FuelAdjustment_Context(ModuleDefinition currentModule) {
 94253983        this.currentModule = currentModule;
 94253984      }
 3985    }
 3986
 3987    class FuelAdjustment_Visitor : ResolverTopDownVisitor<FuelAdjustment_Context> {
 3988      public FuelAdjustment_Visitor(Resolver resolver)
 188503989        : base(resolver) {
 3990        Contract.Requires(resolver != null);
 94253991      }
 3992
 5986603993      protected override bool VisitOneStmt(Statement stmt, ref FuelAdjustment_Context st) {
 5986603994        resolver.CheckForFuelAdjustments(stmt.Tok, stmt.Attributes, st.currentModule);
 5986603995        return true;
 5986603996      }
 3997    }
 3998
 3999    #endregion FuelAdjustmentChecks
 4000
 4001    // ------------------------------------------------------------------------------------------------------
 4002    // ----- ExtremePredicateChecks -------------------------------------------------------------------------
 4003    // ------------------------------------------------------------------------------------------------------
 4004    #region ExtremePredicateChecks
 4005    enum CallingPosition { Positive, Negative, Neither }
 04006    static CallingPosition Invert(CallingPosition cp) {
 04007      switch (cp) {
 04008        case CallingPosition.Positive: return CallingPosition.Negative;
 04009        case CallingPosition.Negative: return CallingPosition.Positive;
 04010        default: return CallingPosition.Neither;
 4011      }
 04012    }
 4013
 4014    class FindFriendlyCalls_Visitor : ResolverTopDownVisitor<CallingPosition> {
 4015      public readonly bool IsCoContext;
 4016      public readonly bool ContinuityIsImportant;
 4017      public FindFriendlyCalls_Visitor(Resolver resolver, bool co, bool continuityIsImportant)
 04018        : base(resolver) {
 4019        Contract.Requires(resolver != null);
 04020        this.IsCoContext = co;
 04021        this.ContinuityIsImportant = continuityIsImportant;
 04022      }
 4023
 04024      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04025        if (expr is UnaryOpExpr) {
 04026          var e = (UnaryOpExpr)expr;
 04027          if (e.Op == UnaryOpExpr.Opcode.Not) {
 4028            // for the sub-parts, use Invert(cp)
 04029            cp = Invert(cp);
 04030            return true;
 4031          }
 04032        } else if (expr is BinaryExpr) {
 04033          var e = (BinaryExpr)expr;
 04034          switch (e.ResolvedOp) {
 4035            case BinaryExpr.ResolvedOpcode.And:
 4036            case BinaryExpr.ResolvedOpcode.Or:
 04037              return true;  // do the sub-parts with the same "cp"
 4038            case BinaryExpr.ResolvedOpcode.Imp:
 04039              Visit(e.E0, Invert(cp));
 04040              Visit(e.E1, cp);
 04041              return false;  // don't recurse (again) on the sub-parts
 4042            default:
 04043              break;
 4044          }
 04045        } else if (expr is NestedMatchExpr) {
 04046          var e = (NestedMatchExpr)expr;
 04047          Visit(e.Source, CallingPosition.Neither);
 04048          var theCp = cp;
 04049          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04050          return false;
 04051        } else if (expr is MatchExpr) {
 04052          var e = (MatchExpr)expr;
 04053          Visit(e.Source, CallingPosition.Neither);
 04054          var theCp = cp;
 04055          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04056          return false;
 04057        } else if (expr is ITEExpr) {
 04058          var e = (ITEExpr)expr;
 04059          Visit(e.Test, CallingPosition.Neither);
 04060          Visit(e.Thn, cp);
 04061          Visit(e.Els, cp);
 04062          return false;
 04063        } else if (expr is LetExpr) {
 04064          var e = (LetExpr)expr;
 04065          foreach (var rhs in e.RHSs) {
 04066            Visit(rhs, CallingPosition.Neither);
 04067          }
 04068          var cpBody = cp;
 04069          if (!e.Exact) {
 4070            // a let-such-that expression introduces an existential that may depend on the _k in a least/greatest predic
 04071            if (IsCoContext && cp == CallingPosition.Positive) {
 04072              cpBody = CallingPosition.Neither;
 04073            } else if (!IsCoContext && cp == CallingPosition.Negative) {
 04074              cpBody = CallingPosition.Neither;
 04075            }
 04076          }
 04077          Visit(e.Body, cpBody);
 04078          return false;
 04079        } else if (expr is QuantifierExpr) {
 04080          var e = (QuantifierExpr)expr;
 04081          Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 04082          var cpos = IsCoContext ? cp : Invert(cp);
 04083          if (ContinuityIsImportant) {
 04084            if ((cpos == CallingPosition.Positive && e is ExistsExpr) || (cpos == CallingPosition.Negative && e is Foral
 04085              if (e.Bounds.Exists(bnd => bnd == null || (bnd.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite)
 4086                // To ensure continuity of extreme predicates, don't allow calls under an existential (resp. universal) 
 4087                // for greatest (resp. least) predicates).
 04088                cp = CallingPosition.Neither;
 04089              }
 04090            }
 04091          }
 04092          Visit(e.LogicalBody(), cp);
 04093          return false;
 04094        } else if (expr is StmtExpr) {
 04095          var e = (StmtExpr)expr;
 04096          Visit(e.E, cp);
 04097          Visit(e.S, CallingPosition.Neither);
 04098          return false;
 04099        } else if (expr is ConcreteSyntaxExpression) {
 4100          // do the sub-parts with the same "cp"
 04101          return true;
 4102        }
 4103        // do the sub-parts with cp := Neither
 04104        cp = CallingPosition.Neither;
 04105        return true;
 04106      }
 4107    }
 4108
 04109    void KNatMismatchError(IToken tok, string contextName, ExtremePredicate.KType contextK, ExtremePredicate.KType calle
 04110      var hint = contextK == ExtremePredicate.KType.Unspecified ? string.Format(" (perhaps try declaring '{0}' as '{0}[n
 04111      reporter.Error(MessageSource.Resolver, tok,
 04112        "this call does not type check, because the context uses a _k parameter of type {0} whereas the callee uses a _k
 04113        contextK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04114        calleeK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04115        hint);
 04116    }
 4117
 4118    class ExtremePredicateChecks_Visitor : FindFriendlyCalls_Visitor {
 4119      readonly ExtremePredicate context;
 4120      public ExtremePredicateChecks_Visitor(Resolver resolver, ExtremePredicate context)
 04121        : base(resolver, context is GreatestPredicate, context.KNat) {
 4122        Contract.Requires(resolver != null);
 4123        Contract.Requires(context != null);
 04124        this.context = context;
 04125      }
 04126      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04127        if (expr is FunctionCallExpr) {
 04128          var e = (FunctionCallExpr)expr;
 04129          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4130            // we're looking at a recursive call
 04131            if (!(context is LeastPredicate ? e.Function is LeastPredicate : e.Function is GreatestPredicate)) {
 04132              resolver.reporter.Error(MessageSource.Resolver, e, "a recursive call from a {0} can go only to other {0}s"
 04133            } else if (context.KNat != ((ExtremePredicate)e.Function).KNat) {
 04134              resolver.KNatMismatchError(e.tok, context.Name, context.TypeOfK, ((ExtremePredicate)e.Function).TypeOfK);
 04135            } else if (cp != CallingPosition.Positive) {
 04136              var msg = string.Format("a {0} can be called recursively only in positive positions", context.WhatKind);
 04137              if (ContinuityIsImportant && cp == CallingPosition.Neither) {
 4138                // this may be inside an non-friendly quantifier
 04139                msg += string.Format(" and cannot sit inside an unbounded {0} quantifier", context is LeastPredicate ? "
 04140              } else {
 4141                // we don't care about the continuity restriction or
 4142                // the extreme-call is not inside an quantifier, so don't bother mentioning the part of existentials/uni
 04143              }
 04144              resolver.reporter.Error(MessageSource.Resolver, e, msg);
 04145            } else {
 04146              e.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 04147              resolver.reporter.Info(MessageSource.Resolver, e.tok, e.Function.Name + "#[_k - 1]");
 04148            }
 04149          }
 4150          // do the sub-parts with cp := Neither
 04151          cp = CallingPosition.Neither;
 04152          return true;
 4153        }
 04154        return base.VisitOneExpr(expr, ref cp);
 04155      }
 04156      protected override bool VisitOneStmt(Statement stmt, ref CallingPosition st) {
 04157        if (stmt is CallStmt) {
 04158          var s = (CallStmt)stmt;
 04159          if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4160            // we're looking at a recursive call
 04161            resolver.reporter.Error(MessageSource.Resolver, stmt.Tok, "a recursive call from a {0} can go only to other 
 04162          }
 4163          // do the sub-parts with the same "cp"
 04164          return true;
 04165        } else {
 04166          return base.VisitOneStmt(stmt, ref st);
 4167        }
 04168      }
 4169    }
 4170
 04171    void ExtremePredicateChecks(Expression expr, ExtremePredicate context, CallingPosition cp) {
 4172      Contract.Requires(expr != null);
 4173      Contract.Requires(context != null);
 04174      var v = new ExtremePredicateChecks_Visitor(this, context);
 04175      v.Visit(expr, cp);
 04176    }
 4177    #endregion ExtremePredicateChecks
 4178
 4179    // ------------------------------------------------------------------------------------------------------
 4180    // ----- ExtremeLemmaChecks -----------------------------------------------------------------------------
 4181    // ------------------------------------------------------------------------------------------------------
 4182    #region ExtremeLemmaChecks
 4183    class ExtremeLemmaChecks_Visitor : ResolverBottomUpVisitor {
 4184      ExtremeLemma context;
 4185      public ExtremeLemmaChecks_Visitor(Resolver resolver, ExtremeLemma context)
 04186        : base(resolver) {
 4187        Contract.Requires(resolver != null);
 4188        Contract.Requires(context != null);
 04189        this.context = context;
 04190      }
 04191      protected override void VisitOneStmt(Statement stmt) {
 04192        if (stmt is CallStmt) {
 04193          var s = (CallStmt)stmt;
 04194          if (s.Method is ExtremeLemma || s.Method is PrefixLemma) {
 4195            // all is cool
 04196          } else {
 4197            // the call goes from an extreme lemma context to a non-extreme-lemma callee
 04198            if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4199              // we're looking at a recursive call (to a non-extreme-lemma)
 04200              resolver.reporter.Error(MessageSource.Resolver, s.Tok, "a recursive call from a {0} can go only to other {
 04201            }
 04202          }
 04203        }
 04204      }
 04205      protected override void VisitOneExpr(Expression expr) {
 04206        if (expr is FunctionCallExpr) {
 04207          var e = (FunctionCallExpr)expr;
 4208          // the call goes from a greatest lemma context to a non-greatest-lemma callee
 04209          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4210            // we're looking at a recursive call (to a non-greatest-lemma)
 04211            resolver.reporter.Error(MessageSource.Resolver, e.tok, "a recursive call from a greatest lemma can go only t
 04212          }
 04213        }
 04214      }
 4215    }
 04216    void ExtremeLemmaChecks(Statement stmt, ExtremeLemma context) {
 4217      Contract.Requires(stmt != null);
 4218      Contract.Requires(context != null);
 04219      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04220      v.Visit(stmt);
 04221    }
 04222    void ExtremeLemmaChecks(Expression expr, ExtremeLemma context) {
 4223      Contract.Requires(context != null);
 04224      if (expr == null) {
 04225        return;
 4226      }
 4227
 04228      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04229      v.Visit(expr);
 04230    }
 4231    #endregion ExtremeLemmaChecks
 4232
 4233    // ------------------------------------------------------------------------------------------------------
 4234    // ----- CheckTypeCharacteristics -----------------------------------------------------------------------
 4235    // ------------------------------------------------------------------------------------------------------
 4236    #region CheckTypeCharacteristics
 51404237    void CheckTypeCharacteristics_Stmt(Statement stmt, bool isGhost) {
 4238      Contract.Requires(stmt != null);
 51404239      var v = new CheckTypeCharacteristics_Visitor(this);
 51404240      v.Visit(stmt, isGhost);
 51404241    }
 154904242    void CheckTypeCharacteristics_Expr(Expression expr, bool isGhost) {
 4243      Contract.Requires(expr != null);
 154904244      var v = new CheckTypeCharacteristics_Visitor(this);
 154904245      v.Visit(expr, isGhost);
 154904246    }
 536554247    public void CheckTypeCharacteristics_Type(IToken tok, Type type, bool isGhost) {
 4248      Contract.Requires(tok != null);
 4249      Contract.Requires(type != null);
 536554250      var v = new CheckTypeCharacteristics_Visitor(this);
 536554251      v.VisitType(tok, type, isGhost);
 536554252    }
 4253
 4254    /// <summary>
 4255    /// This visitor checks that type characteristics are respected in all (implicitly or explicitly)
 4256    /// declared types. Note that equality-support is checked only in compiled contexts.
 4257    /// In addition, this visitor checks that operations that require equality are applied to
 4258    /// types that really do support equality; this, too, is checked only in compiled contexts.
 4259    /// </summary>
 4260    class CheckTypeCharacteristics_Visitor : ResolverTopDownVisitor<bool> {
 4261      public CheckTypeCharacteristics_Visitor(Resolver resolver)
 1485704262        : base(resolver) {
 4263        Contract.Requires(resolver != null);
 742854264      }
 11973204265      protected override bool VisitOneStmt(Statement stmt, ref bool inGhostContext) {
 11973204266        if (stmt.IsGhost) {
 04267          inGhostContext = true;
 04268        }
 4269        // In the sequel, do two things:
 4270        //  * Call VisitType on any type that occurs in the statement
 4271        //  * If the statement introduces ghost components, handle those components here
 4272        //    rather than letting the default visitor handle them
 15384304273        if (stmt is VarDeclStmt) {
 3411104274          var s = (VarDeclStmt)stmt;
 20639704275          foreach (var v in s.Locals) {
 3468804276            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 3468804277          }
 11973204278        } else if (stmt is VarDeclPattern) {
 04279          var s = (VarDeclPattern)stmt;
 04280          foreach (var v in s.LocalVars) {
 04281            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 04282          }
 12311904283        } else if (stmt is AssignStmt) {
 3749804284          var s = (AssignStmt)stmt;
 3749804285          if (s.Rhs is TypeRhs tRhs) {
 04286            VisitType(tRhs.Tok, tRhs.Type, inGhostContext);
 04287          }
 8562104288        } else if (stmt is AssignSuchThatStmt) {
 04289          var s = (AssignSuchThatStmt)stmt;
 04290          Visit(Attributes.SubExpressions(s.Attributes), true);
 04291          Visit(s.Expr, inGhostContext);
 04292          foreach (var lhs in s.Lhss) {
 04293            Visit(lhs, inGhostContext);
 04294          }
 04295          return false;
 4812304296        } else if (stmt is WhileStmt) {
 04297          var s = (WhileStmt)stmt;
 4298          // all subexpressions are ghost, except the guard
 04299          Visit(s.LoopSpecificationExpressions, true);
 04300          if (s.Guard != null) {
 04301            Visit(s.Guard, inGhostContext);
 04302          }
 04303          Visit(s.SubStatements, inGhostContext);
 04304          return false;
 4812304305        } else if (stmt is AlternativeLoopStmt) {
 04306          var s = (AlternativeLoopStmt)stmt;
 4307          // all subexpressions are ghost, except the guards
 04308          Visit(s.LoopSpecificationExpressions, true);
 04309          foreach (var alt in s.Alternatives) {
 04310            Visit(alt.Guard, inGhostContext);
 04311          }
 04312          Visit(s.SubStatements, inGhostContext);
 04313          return false;
 4812304314        } else if (stmt is ForLoopStmt) {
 04315          var s = (ForLoopStmt)stmt;
 4316          // all subexpressions are ghost, except the bounds
 04317          Visit(s.LoopSpecificationExpressions, true);
 04318          Visit(s.Start, inGhostContext);
 04319          if (s.End != null) {
 04320            Visit(s.End, inGhostContext);
 04321          }
 04322          Visit(s.SubStatements, inGhostContext);
 04323          return false;
 4928804324        } else if (stmt is CallStmt) {
 116504325          var s = (CallStmt)stmt;
 116504326          CheckTypeInstantiation(s.Tok, s.Method.WhatKind, s.Method.Name, s.Method.TypeArgs, s.MethodSelect.TypeApplicat
 4327          // recursively visit all subexpressions, noting that some of them may correspond to ghost formal parameters
 116504328          Contract.Assert(s.Lhs.Count == s.Method.Outs.Count);
 755604329          for (var i = 0; i < s.Method.Outs.Count; i++) {
 174204330            Visit(s.Lhs[i], inGhostContext || s.Method.Outs[i].IsGhost);
 174204331          }
 116504332          Visit(s.Receiver, inGhostContext);
 116504333          Contract.Assert(s.Args.Count == s.Method.Ins.Count);
 1131504334          for (var i = 0; i < s.Method.Ins.Count; i++) {
 299504335            Visit(s.Args[i], inGhostContext || s.Method.Ins[i].IsGhost);
 299504336          }
 116504337          return false;
 4695804338        } else if (stmt is ForallStmt) {
 04339          var s = (ForallStmt)stmt;
 04340          foreach (var v in s.BoundVars) {
 04341            VisitType(v.Tok, v.Type, inGhostContext);
 04342          }
 4343          // do substatements and subexpressions, noting that ensures clauses are ghost
 04344          Visit(Attributes.SubExpressions(s.Attributes), true);
 04345          if (s.Range != null) {
 04346            Visit(s.Range, inGhostContext);
 04347          }
 04348          foreach (var ee in s.Ens) {
 04349            Visit(Attributes.SubExpressions(ee.Attributes), true);
 04350            Visit(ee.E, true);
 04351          }
 04352          Visit(s.SubStatements, inGhostContext);
 04353          return false;
 4695804354        } else if (stmt is ExpectStmt) {
 04355          var s = (ExpectStmt)stmt;
 04356          Visit(Attributes.SubExpressions(s.Attributes), true);
 04357          Visit(s.Expr, inGhostContext);
 04358          if (s.Message != null) {
 04359            Visit(s.Message, inGhostContext);
 04360          }
 04361          return false;
 4362        }
 11856704363        return true;
 11973204364      }
 4365
 27430304366      protected override bool VisitOneExpr(Expression expr, ref bool inGhostContext) {
 4367        // Do two things:
 4368        //  * Call VisitType on any type that occurs in the statement
 4369        //  * If the expression introduces ghost components, handle those components here
 4370        //    rather than letting the default visitor handle them
 28106404371        if (expr is BinaryExpr && !inGhostContext) {
 676104372          var e = (BinaryExpr)expr;
 676104373          var t0 = e.E0.Type.NormalizeExpand();
 676104374          var t1 = e.E1.Type.NormalizeExpand();
 676104375          switch (e.Op) {
 4376            case BinaryExpr.Opcode.Eq:
 4377            case BinaryExpr.Opcode.Neq:
 4378              // First, check some special cases that can always be compared against--for example, a datatype value (lik
 38204379              if (CanCompareWith(e.E0)) {
 4380                // that's cool
 19104381              } else if (CanCompareWith(e.E1)) {
 4382                // oh yeah!
 04383              } else if (!t0.PartiallySupportsEquality) {
 04384                resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of types t
 04385              } else if (!t1.PartiallySupportsEquality) {
 04386                resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of types t
 04387              }
 19104388              break;
 4389            default:
 657004390              switch (e.ResolvedOp) {
 4391                // Note, all operations on sets, multisets, and maps are guaranteed to work because of restrictions plac
 4392                // these types are instantiated.  (Except: This guarantee does not apply to equality on maps, because th
 4393                // of maps is not restricted, only the Domain type.  However, the equality operator is checked above.)
 4394                case BinaryExpr.ResolvedOpcode.InSeq:
 4395                case BinaryExpr.ResolvedOpcode.NotInSeq:
 4396                case BinaryExpr.ResolvedOpcode.Prefix:
 4397                case BinaryExpr.ResolvedOpcode.ProperPrefix:
 5104398                  if (!t1.SupportsEquality) {
 04399                    resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of seq
 5104400                  } else if (!t0.SupportsEquality) {
 04401                    if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.InSet || e.ResolvedOp == BinaryExpr.ResolvedOpcode.Not
 04402                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of t
 04403                    } else {
 04404                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of s
 04405                    }
 04406                  }
 5104407                  break;
 4408                default:
 651904409                  break;
 4410              }
 657004411              break;
 4412          }
 27478204413        } else if (expr is ComprehensionExpr) {
 47904414          var e = (ComprehensionExpr)expr;
 494404415          foreach (var bv in e.BoundVars) {
 116904416            VisitType(bv.tok, bv.Type, inGhostContext);
 116904417          }
 27119204418        } else if (expr is LetExpr) {
 365004419          var e = (LetExpr)expr;
 365004420          Visit(Attributes.SubExpressions(e.Attributes), true);
 730004421          if (e.Exact) {
 365004422            Contract.Assert(e.LHSs.Count == e.RHSs.Count);
 1825004423            for (var i = 0; i < e.LHSs.Count; i++) {
 4424              // The VisitPattern function visits all BoundVar's in a pattern and returns
 4425              // "true" if all variables are ghost.
 365004426              bool VisitPattern(CasePattern<BoundVar> pat, bool patternGhostContext) {
 730004427                if (pat.Var != null) {
 365004428                  VisitType(pat.tok, pat.Var.Type, patternGhostContext || pat.Var.IsGhost);
 365004429                  return pat.Var.IsGhost;
 04430                } else {
 04431                  var allGhost = true;
 04432                  Contract.Assert(pat.Ctor != null);
 04433                  Contract.Assert(pat.Ctor.Formals.Count == pat.Arguments.Count);
 04434                  for (var i = 0; i < pat.Ctor.Formals.Count; i++) {
 04435                    var formal = pat.Ctor.Formals[i];
 04436                    var arg = pat.Arguments[i];
 4437                    // don't use short-circuit booleans in the following line, because we want to visit all nested patte
 04438                    allGhost &= VisitPattern(arg, patternGhostContext || formal.IsGhost);
 04439                  }
 04440                  return allGhost;
 4441                }
 365004442              }
 4443
 365004444              var allGhosts = VisitPattern(e.LHSs[i], inGhostContext);
 365004445              Visit(e.RHSs[i], inGhostContext || allGhosts);
 365004446            }
 365004447          } else {
 04448            Contract.Assert(e.RHSs.Count == 1);
 04449            var allGhost = true;
 04450            foreach (var bv in e.BoundVars) {
 04451              if (!bv.IsGhost) {
 04452                allGhost = false;
 04453              }
 04454              VisitType(bv.tok, bv.Type, inGhostContext || bv.IsGhost);
 04455            }
 04456            Visit(e.RHSs[0], inGhostContext || allGhost);
 04457          }
 365004458          Visit(e.Body, inGhostContext);
 365004459          return false;
 26457704460        } else if (expr is MemberSelectExpr) {
 116404461          var e = (MemberSelectExpr)expr;
 138704462          if (e.Member is Function || e.Member is Method) {
 22304463            CheckTypeInstantiation(e.tok, e.Member.WhatKind, e.Member.Name, ((ICallable)e.Member).TypeArgs, e.TypeApplic
 22304464          }
 26423004465        } else if (expr is FunctionCallExpr) {
 81704466          var e = (FunctionCallExpr)expr;
 81704467          CheckTypeInstantiation(e.tok, e.Function.WhatKind, e.Function.Name, e.Function.TypeArgs, e.TypeApplication_Jus
 4468          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 81704469          Visit(e.Receiver, inGhostContext);
 81704470          Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 808104471          for (var i = 0; i < e.Args.Count; i++) {
 214904472            Visit(e.Args[i], inGhostContext || e.Function.Formals[i].IsGhost);
 214904473          }
 81704474          return false;  // we've done what there is to be done
 27730704475        } else if (expr is DatatypeValue) {
 1587504476          var e = (DatatypeValue)expr;
 4477          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 1587504478          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 12146804479          for (var i = 0; i < e.Arguments.Count; i++) {
 2990604480            Visit(e.Arguments[i], inGhostContext || e.Ctor.Formals[i].IsGhost);
 2990604481          }
 1587504482          return false;  // we've done what there is to be done
 24555704483        } else if (expr is SetDisplayExpr || expr is MultiSetDisplayExpr || expr is MapDisplayExpr || expr is SeqConstru
 25689404484                   expr is MultiSetFormingExpr || expr is StaticReceiverExpr) {
 4485          // This catches other expressions whose type may potentially be illegal
 1133704486          VisitType(expr.tok, expr.Type, inGhostContext);
 24555704487        } else if (expr is StmtExpr) {
 04488          var e = (StmtExpr)expr;
 04489          Visit(e.S, true);
 04490          Visit(e.E, inGhostContext);
 04491          return false;
 4492        }
 25396104493        return true;
 27430304494      }
 4495
 15013304496      public void VisitType(IToken tok, Type type, bool inGhostContext) {
 4497        Contract.Requires(tok != null);
 4498        Contract.Requires(type != null);
 15013304499        type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or
 22958054500        if (type is BasicType) {
 4501          // fine
 16270804502        } else if (type is SetType) {
 1257504503          var st = (SetType)type;
 1257504504          var argType = st.Arg;
 1257504505          if (!inGhostContext && !argType.SupportsEquality) {
 04506            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}set argument type must support equality (got {0}){1
 04507          }
 1257504508          VisitType(tok, argType, inGhostContext);
 4509
 8316654510        } else if (type is MultiSetType) {
 1248104511          var argType = ((MultiSetType)type).Arg;
 1248104512          if (!inGhostContext && !argType.SupportsEquality) {
 04513            resolver.reporter.Error(MessageSource.Resolver, tok, "multiset argument type must support equality (got {0})
 4514
 04515          }
 1248104516          VisitType(tok, argType, inGhostContext);
 5811054517        } else if (type is MapType) {
 04518          var mt = (MapType)type;
 04519          if (!inGhostContext && !mt.Domain.SupportsEquality) {
 04520            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}map domain type must support equality (got {0}){1}"
 04521          }
 04522          VisitType(tok, mt.Domain, inGhostContext);
 04523          VisitType(tok, mt.Range, inGhostContext);
 4524
 5525954525        } else if (type is SeqType) {
 963004526          Type argType = ((SeqType)type).Arg;
 963004527          VisitType(tok, argType, inGhostContext);
 4528
 8162904529        } else if (type is UserDefinedType) {
 3599954530          var udt = (UserDefinedType)type;
 3599954531          Contract.Assert(udt.ResolvedClass != null);
 3599954532          var formalTypeArgs = udt.ResolvedClass.TypeArgs;
 3599954533          Contract.Assert(formalTypeArgs != null);
 3599954534          CheckTypeInstantiation(udt.tok, "type", udt.ResolvedClass.Name, formalTypeArgs, udt.TypeArgs, inGhostContext);
 4535
 3599954536        } else if (type is TypeProxy) {
 4537          // the type was underconstrained; this is checked elsewhere, but it is not in violation of the equality-type t
 04538        } else {
 04539          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4540        }
 15013304541      }
 4542
 3820454543      void CheckTypeInstantiation(IToken tok, string what, string className, List<TypeParameter> formalTypeArgs, List<Ty
 4544        Contract.Requires(tok != null);
 4545        Contract.Requires(what != null);
 4546        Contract.Requires(className != null);
 4547        Contract.Requires(formalTypeArgs != null);
 4548        Contract.Requires(actualTypeArgs != null);
 4549        Contract.Requires(formalTypeArgs.Count == actualTypeArgs.Count);
 4550
 25412154551        for (var i = 0; i < formalTypeArgs.Count; i++) {
 5923754552          var formal = formalTypeArgs[i];
 5923754553          var actual = actualTypeArgs[i];
 5923754554          if (!CheckCharacteristics(formal.Characteristics, actual, inGhostContext, out var whatIsWrong, out var hint)) 
 04555            resolver.reporter.Error(MessageSource.Resolver, tok, "type parameter{0} ({1}) passed to {2} {3} must support
 04556              actualTypeArgs.Count == 1 ? "" : " " + i, formal.Name, what, className, whatIsWrong, actual, hint);
 04557          }
 5923754558          VisitType(tok, actual, inGhostContext);
 5923754559        }
 3820454560      }
 4561
 5923754562      bool CheckCharacteristics(TypeParameter.TypeParameterCharacteristics formal, Type actual, bool inGhostContext, out
 4563        Contract.Ensures(Contract.Result<bool>() || (Contract.ValueAtReturn(out whatIsWrong) != null && Contract.ValueAt
 5923754564        if (!inGhostContext && formal.EqualitySupport != TypeParameter.EqualitySupportValue.Unspecified && !actual.Suppo
 04565          whatIsWrong = "equality";
 04566          hint = TypeEqualityErrorMessageHint(actual);
 04567          return false;
 4568        }
 5923754569        var cl = (actual.Normalize() as UserDefinedType)?.ResolvedClass;
 5923754570        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 5923754571        if (formal.HasCompiledValue && (inGhostContext ? !actual.IsNonempty : !actual.HasCompilableValue)) {
 04572          whatIsWrong = "auto-initialization";
 04573          hint = tp == null ? "" :
 04574            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(0)', which says it can only be instanti
 04575          return false;
 4576        }
 5923754577        if (formal.IsNonempty && !actual.IsNonempty) {
 04578          whatIsWrong = "nonempty";
 04579          hint = tp == null ? "" :
 04580            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(00)', which says it can only be instant
 04581          return false;
 4582        }
 5923754583        if (formal.ContainsNoReferenceTypes && actual.MayInvolveReferences) {
 04584          whatIsWrong = "no references";
 04585          hint = tp == null ? "" :
 04586            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(!new)', which says it can only be insta
 04587          return false;
 4588        }
 5923754589        whatIsWrong = null;
 5923754590        hint = null;
 5923754591        return true;
 5923754592      }
 4593
 04594      string TypeEqualityErrorMessageHint(Type argType) {
 4595        Contract.Requires(argType != null);
 04596        var cl = (argType.Normalize() as UserDefinedType)?.ResolvedClass;
 04597        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 04598        if (tp != null) {
 04599          return string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(==)', which says it can only be in
 4600        }
 04601        return "";
 04602      }
 4603    }
 4604
 24154605    public static bool CanCompareWith(Expression expr) {
 4606      Contract.Requires(expr != null);
 48304607      if (expr.Type.SupportsEquality) {
 24154608        return true;
 4609      }
 04610      expr = expr.Resolved;
 04611      if (expr is DatatypeValue datatypeValue && !datatypeValue.Ctor.EnclosingDatatype.HasGhostVariant) {
 04612        for (var i = 0; i < datatypeValue.Ctor.Formals.Count; i++) {
 04613          if (datatypeValue.Ctor.Formals[i].IsGhost) {
 04614            return false;
 04615          } else if (!CanCompareWith(datatypeValue.Arguments[i])) {
 04616            return false;
 4617          }
 04618        }
 04619        return true;
 04620      } else if (expr is DisplayExpression) {
 04621        var e = (DisplayExpression)expr;
 04622        return e.Elements.Count == 0;
 04623      } else if (expr is MapDisplayExpr) {
 04624        var e = (MapDisplayExpr)expr;
 04625        return e.Elements.Count == 0;
 4626      }
 04627      return false;
 24154628    }
 4629
 4630    #endregion CheckTypeCharacteristics
 4631
 4632    // ------------------------------------------------------------------------------------------------------
 4633    // ----- ComputeGhostInterest ---------------------------------------------------------------------------
 4634    // ------------------------------------------------------------------------------------------------------
 4635    #region ComputeGhostInterest
 51404636    public void ComputeGhostInterest(Statement stmt, bool mustBeErasable, [CanBeNull] string proofContext, ICodeContext 
 4637      Contract.Requires(stmt != null);
 4638      Contract.Requires(codeContext != null);
 51404639      var visitor = new GhostInterestVisitor(codeContext, this, reporter, false, codeContext is Method);
 51404640      visitor.Visit(stmt, mustBeErasable, proofContext);
 51404641    }
 4642
 4643    #endregion
 4644
 4645    // ------------------------------------------------------------------------------------------------------
 4646    // ----- FillInDefaultLoopDecreases ---------------------------------------------------------------------
 4647    // ------------------------------------------------------------------------------------------------------
 4648    #region FillInDefaultLoopDecreases
 4649    class FillInDefaultLoopDecreases_Visitor : ResolverBottomUpVisitor {
 4650      readonly ICallable EnclosingMethod;
 4651      public FillInDefaultLoopDecreases_Visitor(Resolver resolver, ICallable enclosingMethod)
 51404652        : base(resolver) {
 4653        Contract.Requires(resolver != null);
 4654        Contract.Requires(enclosingMethod != null);
 25704655        EnclosingMethod = enclosingMethod;
 25704656      }
 5986604657      protected override void VisitOneStmt(Statement stmt) {
 5986604658        if (stmt is WhileStmt) {
 04659          var s = (WhileStmt)stmt;
 04660          resolver.FillInDefaultLoopDecreases(s, s.Guard, s.Decreases.Expressions, EnclosingMethod);
 5986604661        } else if (stmt is AlternativeLoopStmt) {
 04662          var s = (AlternativeLoopStmt)stmt;
 04663          resolver.FillInDefaultLoopDecreases(s, null, s.Decreases.Expressions, EnclosingMethod);
 04664        }
 5986604665      }
 4666    }
 4667    #endregion FillInDefaultLoopDecreases
 4668
 4669    // ------------------------------------------------------------------------------------------------------
 4670    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4671    // ------------------------------------------------------------------------------------------------------
 4672    #region ReportOtherAdditionalInformation_Visitor
 4673    class ReportOtherAdditionalInformation_Visitor : ResolverBottomUpVisitor {
 4674      public ReportOtherAdditionalInformation_Visitor(Resolver resolver)
 51404675        : base(resolver) {
 4676        Contract.Requires(resolver != null);
 25704677      }
 5986604678      protected override void VisitOneStmt(Statement stmt) {
 5986604679        if (stmt is ForallStmt) {
 04680          var s = (ForallStmt)stmt;
 04681          if (s.Kind == ForallStmt.BodyKind.Call) {
 04682            var cs = (CallStmt)s.S0;
 4683            // show the callee's postcondition as the postcondition of the 'forall' statement
 4684            // TODO:  The following substitutions do not correctly take into consideration variable capture; hence, what
 04685            var argsSubstMap = new Dictionary<IVariable, Expression>();  // maps formal arguments to actuals
 04686            Contract.Assert(cs.Method.Ins.Count == cs.Args.Count);
 04687            for (int i = 0; i < cs.Method.Ins.Count; i++) {
 04688              argsSubstMap.Add(cs.Method.Ins[i], cs.Args[i]);
 04689            }
 04690            var substituter = new AlphaConvertingSubstituter(cs.Receiver, argsSubstMap, new Dictionary<TypeParameter, Ty
 04691            if (!Attributes.Contains(s.Attributes, "auto_generated")) {
 04692              foreach (var ens in cs.Method.Ens) {
 04693                var p = substituter.Substitute(ens.E);  // substitute the call's actuals for the method's formals
 04694                resolver.reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(resolver.Options
 04695              }
 04696            }
 04697          }
 04698        }
 5986604699      }
 4700    }
 4701    #endregion ReportOtherAdditionalInformation_Visitor
 4702
 4703    // ------------------------------------------------------------------------------------------------------
 4704    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4705    // ------------------------------------------------------------------------------------------------------
 4706    #region CheckDividedConstructorInit
 4707    class CheckDividedConstructorInit_Visitor : ResolverTopDownVisitor<int> {
 4708      public CheckDividedConstructorInit_Visitor(Resolver resolver)
 26704709        : base(resolver) {
 4710        Contract.Requires(resolver != null);
 13354711      }
 04712      public void CheckInit(List<Statement> initStmts) {
 4713        Contract.Requires(initStmts != null);
 04714        initStmts.Iter(CheckInit);
 04715      }
 4716      /// <summary>
 4717      /// This method almost does what Visit(Statement) does, except that it handles assignments to
 4718      /// fields differently.
 4719      /// </summary>
 04720      void CheckInit(Statement stmt) {
 4721        Contract.Requires(stmt != null);
 4722        // Visit(stmt) would do:
 4723        //     stmt.SubExpressions.Iter(Visit);    (*)
 4724        //     stmt.SubStatements.Iter(Visit);     (**)
 4725        //     VisitOneStmt(stmt);                 (***)
 4726        // We may do less for (*), we always use CheckInit instead of Visit in (**), and we do (***) the same.
 04727        if (stmt is AssignStmt) {
 04728          var s = stmt as AssignStmt;
 4729          // The usual visitation of s.SubExpressions.Iter(Visit) would do the following:
 4730          //   Attributes.SubExpressions(s.Attributes).Iter(Visit);  (+)
 4731          //   Visit(s.Lhs);                                         (++)
 4732          //   s.Rhs.SubExpressions.Iter(Visit);                     (+++)
 4733          // Here, we may do less; in particular, we may omit (++).
 04734          Attributes.SubExpressions(s.Attributes).Iter(VisitExpr);  // (+)
 04735          var mse = s.Lhs as MemberSelectExpr;
 04736          if (mse != null && Expression.AsThis(mse.Obj) != null) {
 04737            if (s.Rhs is ExprRhs) {
 4738              // This is a special case we allow.  Omit s.Lhs in the recursive visits.  That is, we omit (++).
 4739              // Furthermore, because the assignment goes to a field of "this" and won't be available until after
 4740              // the "new;", we can allow certain specific (and useful) uses of "this" in the RHS.
 04741              s.Rhs.SubExpressions.Iter(LiberalRHSVisit);  // (+++)
 04742            } else {
 04743              s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04744            }
 04745          } else {
 04746            VisitExpr(s.Lhs);  // (++)
 04747            s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04748          }
 04749        } else {
 04750          stmt.SubExpressions.Iter(VisitExpr);  // (*)
 04751        }
 04752        stmt.SubStatements.Iter(CheckInit);  // (**)
 04753        int dummy = 0;
 04754        VisitOneStmt(stmt, ref dummy);  // (***)
 04755      }
 04756      void VisitExpr(Expression expr) {
 4757        Contract.Requires(expr != null);
 04758        Visit(expr, 0);
 04759      }
 04760      protected override bool VisitOneExpr(Expression expr, ref int unused) {
 04761        if (expr is MemberSelectExpr) {
 04762          var e = (MemberSelectExpr)expr;
 04763          if (e.Member.IsInstanceIndependentConstant && Expression.AsThis(e.Obj) != null) {
 04764            return false;  // don't continue the recursion
 4765          }
 04766        } else if (expr is ThisExpr && !(expr is ImplicitThisExpr_ConstructorCall)) {
 04767          resolver.reporter.Error(MessageSource.Resolver, expr.tok, "in the first division of the constructor body (befo
 04768        }
 04769        return base.VisitOneExpr(expr, ref unused);
 04770      }
 04771      void LiberalRHSVisit(Expression expr) {
 4772        Contract.Requires(expr != null);
 4773        // It is important not to allow "this" to flow into something that can be used (for compilation or
 4774        // verification purposes) before the "new;", because, to the verifier, "this" has not yet been allocated.
 4775        // The verifier is told that everything reachable from the heap is expected to be allocated and satisfy all
 4776        // the usual properties, so "this" had better not become reachable from the heap until after the "new;"
 4777        // that does the actual allocation of "this".
 4778        // Within these restrictions, we can allow the (not yet fully available) value "this" to flow into values
 4779        // stored in fields of "this".  Such values are naked occurrences of "this" and "this" occurring
 4780        // as part of constructing a value type.  Since by this rule, "this" may be part of the value stored in
 4781        // a field of "this", we must apply the same rules to uses of the values of fields of "this".
 04782        if (expr is ConcreteSyntaxExpression) {
 04783        } else if (expr is ThisExpr) {
 04784        } else if (expr is MemberSelectExpr && IsThisDotField((MemberSelectExpr)expr)) {
 04785        } else if (expr is SetDisplayExpr) {
 04786        } else if (expr is MultiSetDisplayExpr) {
 04787        } else if (expr is SeqDisplayExpr) {
 04788        } else if (expr is MapDisplayExpr) {
 04789        } else if (expr is BinaryExpr && IsCollectionOperator(((BinaryExpr)expr).ResolvedOp)) {
 04790        } else if (expr is DatatypeValue) {
 04791        } else if (expr is ITEExpr) {
 04792          var e = (ITEExpr)expr;
 04793          VisitExpr(e.Test);
 04794          LiberalRHSVisit(e.Thn);
 04795          LiberalRHSVisit(e.Els);
 04796          return;
 04797        } else {
 4798          // defer to the usual Visit
 04799          VisitExpr(expr);
 04800          return;
 4801        }
 04802        expr.SubExpressions.Iter(LiberalRHSVisit);
 04803      }
 04804      static bool IsThisDotField(MemberSelectExpr expr) {
 4805        Contract.Requires(expr != null);
 04806        return Expression.AsThis(expr.Obj) != null && expr.Member is Field;
 04807      }
 04808      static bool IsCollectionOperator(BinaryExpr.ResolvedOpcode op) {
 04809        switch (op) {
 4810          // sets:  +, *, -
 4811          case BinaryExpr.ResolvedOpcode.Union:
 4812          case BinaryExpr.ResolvedOpcode.Intersection:
 4813          case BinaryExpr.ResolvedOpcode.SetDifference:
 4814          // multisets: +, *, -
 4815          case BinaryExpr.ResolvedOpcode.MultiSetUnion:
 4816          case BinaryExpr.ResolvedOpcode.MultiSetIntersection:
 4817          case BinaryExpr.ResolvedOpcode.MultiSetDifference:
 4818          // sequences: +
 4819          case BinaryExpr.ResolvedOpcode.Concat:
 4820          // maps: +, -
 4821          case BinaryExpr.ResolvedOpcode.MapMerge:
 4822          case BinaryExpr.ResolvedOpcode.MapSubtraction:
 04823            return true;
 4824          default:
 04825            return false;
 4826        }
 04827      }
 4828    }
 4829    #endregion
 4830
 4831    // ------------------------------------------------------------------------------------------------------
 4832    // ------------------------------------------------------------------------------------------------------
 4833    // ------------------------------------------------------------------------------------------------------
 4834
 507304835    bool InferRequiredEqualitySupport(TypeParameter tp, Type type) {
 4836      Contract.Requires(tp != null);
 4837      Contract.Requires(type != null);
 4838
 507304839      type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or s
 640804840      if (type is BasicType) {
 507304841      } else if (type is SetType) {
 04842        var st = (SetType)type;
 04843        return st.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, st.Arg);
 373804844      } else if (type is MultiSetType) {
 04845        var ms = (MultiSetType)type;
 04846        return ms.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, ms.Arg);
 373804847      } else if (type is MapType) {
 04848        var mt = (MapType)type;
 04849        return mt.Domain.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, mt.Domain) || InferRequiredEqualitySu
 560704850      } else if (type is SeqType) {
 186904851        var sq = (SeqType)type;
 186904852        return InferRequiredEqualitySupport(tp, sq.Arg);
 373804853      } else if (type is UserDefinedType) {
 186904854        var udt = (UserDefinedType)type;
 186904855        List<TypeParameter> formalTypeArgs = udt.ResolvedClass.TypeArgs;
 186904856        Contract.Assert(formalTypeArgs != null);
 186904857        Contract.Assert(formalTypeArgs.Count == udt.TypeArgs.Count);
 186904858        var i = 0;
 574054859        foreach (var argType in udt.TypeArgs) {
 4454860          var formalTypeArg = formalTypeArgs[i];
 4454861          if ((formalTypeArg.SupportsEquality && argType.AsTypeParameter == tp) || InferRequiredEqualitySupport(tp, argT
 04862            return true;
 4863          }
 4454864          i++;
 4454865        }
 186904866        if (udt.ResolvedClass is TypeSynonymDecl) {
 04867          var syn = (TypeSynonymDecl)udt.ResolvedClass;
 04868          if (syn.IsRevealedInScope(Type.GetScope())) {
 04869            return InferRequiredEqualitySupport(tp, syn.RhsWithArgument(udt.TypeArgs));
 4870          }
 04871        }
 186904872      } else {
 04873        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4874      }
 320404875      return false;
 507304876    }
 4877
 4878    TopLevelDeclWithMembers currentClass;
 4879    public Method currentMethod;
 4880    readonly Scope<TypeParameter>/*!*/ allTypeParameters;
 4881    public readonly Scope<IVariable>/*!*/ scope;
 4882    Scope<Statement>/*!*/ enclosingStatementLabels;
 4883    public readonly Scope<Label>/*!*/ DominatingStatementLabels;
 4454884    List<Statement> loopStack = new List<Statement>();  // the enclosing loops (from which it is possible to break out)
 4885
 4886    /// <summary>
 4887    /// Resolves the types along .ParentTraits and fills in .ParentTraitHeads
 4888    /// </summary>
 8904889    void ResolveParentTraitTypes(TopLevelDeclWithMembers cl, Graph<TopLevelDeclWithMembers> parentRelation) {
 4890      Contract.Requires(cl != null);
 4891      Contract.Requires(currentClass == null);
 4892      Contract.Ensures(currentClass == null);
 4893
 8904894      currentClass = cl;
 8904895      allTypeParameters.PushMarker();
 8904896      ResolveTypeParameters(cl.TypeArgs, false, cl);
 26704897      foreach (var tt in cl.ParentTraits) {
 04898        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04899        ResolveType(cl.tok, tt, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOptionEnum.DontInfer, null);
 04900        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 04901          var udt = tt as UserDefinedType;
 04902          if (udt != null && udt.ResolvedClass is NonNullTypeDecl nntd && nntd.ViewAsClass is TraitDecl trait) {
 4903            // disallowing inheritance in multi module case
 04904            bool termination = true;
 04905            if (cl.EnclosingModuleDefinition == trait.EnclosingModuleDefinition || trait.IsObjectTrait || (Attributes.Co
 4906              // all is good (or the user takes responsibility for the lack of termination checking)
 04907              if (!cl.ParentTraitHeads.Contains(trait)) {
 04908                cl.ParentTraitHeads.Add(trait);
 04909                parentRelation.AddEdge(cl, trait);
 04910              }
 04911            } else {
 04912              reporter.Error(MessageSource.Resolver, udt.tok, "{0} '{1}' is in a different module than trait '{2}'. A {0
 04913            }
 04914          } else {
 04915            reporter.Error(MessageSource.Resolver, udt != null ? udt.tok : cl.tok, "a {0} can only extend traits (found 
 04916          }
 04917        }
 04918      }
 8904919      allTypeParameters.PopMarker();
 8904920      currentClass = null;
 8904921    }
 4922
 4923    /// <summary>
 4924    /// This method idempotently fills in .InheritanceInformation, .ParentFormalTypeParametersToActuals, and the
 4925    /// name->MemberDecl table for "cl" and the transitive parent traits of "cl". It also checks that every (transitive)
 4926    /// parent trait is instantiated with the same type parameters
 4927    /// The method assumes that all types along .ParentTraits have been successfully resolved and .ParentTraitHeads been
 4928    /// </summary>
 8904929    void RegisterInheritedMembers(TopLevelDeclWithMembers cl) {
 4930      Contract.Requires(cl != null);
 4931
 8904932      if (cl.ParentTypeInformation != null) {
 04933        return;
 4934      }
 8904935      cl.ParentTypeInformation = new TopLevelDeclWithMembers.InheritanceInformationClass();
 4936
 4937      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the immediate parent traits
 26704938      foreach (var tt in cl.ParentTraits) {
 04939        var udt = (UserDefinedType)tt;
 04940        var nntd = (NonNullTypeDecl)udt.ResolvedClass;
 04941        var trait = (TraitDecl)nntd.ViewAsClass;
 04942        cl.ParentTypeInformation.Record(trait, udt);
 04943        Contract.Assert(trait.TypeArgs.Count == udt.TypeArgs.Count);
 04944        for (var i = 0; i < trait.TypeArgs.Count; i++) {
 4945          // there may be duplciate parent traits, which haven't been checked for yet, so add mapping only for the first
 04946          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(trait.TypeArgs[i])) {
 04947            cl.ParentFormalTypeParametersToActuals.Add(trait.TypeArgs[i], udt.TypeArgs[i]);
 04948          }
 04949        }
 04950      }
 4951
 4952      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the transitive parent traits
 26704953      foreach (var trait in cl.ParentTraitHeads) {
 4954        // make sure the parent trait has been processed; then, incorporate its inheritance information
 04955        RegisterInheritedMembers(trait);
 04956        cl.ParentTypeInformation.Extend(trait, trait.ParentTypeInformation, cl.ParentFormalTypeParametersToActuals);
 04957        foreach (var entry in trait.ParentFormalTypeParametersToActuals) {
 04958          var v = entry.Value.Subst(cl.ParentFormalTypeParametersToActuals);
 04959          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(entry.Key)) {
 04960            cl.ParentFormalTypeParametersToActuals.Add(entry.Key, v);
 04961          }
 04962        }
 04963      }
 4964
 4965      // Check that every (transitive) parent trait is instantiated with the same type parameters
 26704966      foreach (var group in cl.ParentTypeInformation.GetTypeInstantiationGroups()) {
 04967        Contract.Assert(1 <= group.Count);
 04968        var ty = group[0].Item1;
 04969        for (var i = 1; i < group.Count; i++) {
 04970          if (!group.GetRange(0, i).Exists(pair => pair.Item1.Equals(group[i].Item1))) {
 04971            var via0 = group[0].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[0].Item2, traitDecl => traitDecl.Nam
 04972            var via1 = group[i].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[i].Item2, traitDecl => traitDecl.Nam
 04973            reporter.Error(MessageSource.Resolver, cl.tok,
 04974              "duplicate trait parents with the same head type must also have the same type arguments; got {0}{1} and {2
 04975              ty, via0, group[i].Item1, via1);
 04976          }
 04977        }
 04978      }
 4979
 4980      // Update the name->MemberDecl table for the class. Report an error if the same name refers to more than one membe
 4981      // except when such duplication is purely that one member, say X, is inherited and the other is an override of X.
 8904982      var inheritedMembers = new Dictionary<string, MemberDecl>();
 26704983      foreach (var trait in cl.ParentTraitHeads) {
 04984        foreach (var traitMember in classMembers[trait].Values) {  // TODO: rather than using .Values, it would be nice 
 04985          if (!inheritedMembers.TryGetValue(traitMember.Name, out var prevMember)) {
 4986            // record "traitMember" as an inherited member
 04987            inheritedMembers.Add(traitMember.Name, traitMember);
 04988          } else if (traitMember == prevMember) {
 4989            // same member, inherited two different ways
 04990          } else if (traitMember.Overrides(prevMember)) {
 4991            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "traitMember" is an o
 04992            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4993            // re-map "traitMember.Name" to point to the overriding member
 04994            inheritedMembers[traitMember.Name] = traitMember;
 04995          } else if (prevMember.Overrides(traitMember)) {
 4996            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "prevMember" is an ov
 04997            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4998            // keep the mapping to "prevMember"
 04999          } else {
 5000            // "prevMember" and "traitMember" refer to different members (with the same name)
 05001            reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' inherits a member named '{2}' from both traits '{3
 05002              cl.WhatKind, cl.Name, traitMember.Name, prevMember.EnclosingClass.Name, traitMember.EnclosingClass.Name);
 05003          }
 05004        }
 05005      }
 5006      // Incorporate the inherited members into the name->MemberDecl mapping of "cl"
 8905007      var members = classMembers[cl];
 26705008      foreach (var entry in inheritedMembers) {
 05009        var name = entry.Key;
 05010        var traitMember = entry.Value;
 05011        if (!members.TryGetValue(name, out var clMember)) {
 05012          members.Add(name, traitMember);
 05013        } else {
 05014          Contract.Assert(clMember.EnclosingClass == cl);  // sanity check
 05015          Contract.Assert(clMember.OverriddenMember == null);  // sanity check
 05016          clMember.OverriddenMember = traitMember;
 05017        }
 05018      }
 8905019    }
 5020
 5021    /// <summary>
 5022    /// Assumes type parameters have already been pushed
 5023    /// </summary>
 8905024    void ResolveClassMemberTypes(TopLevelDeclWithMembers cl) {
 5025      Contract.Requires(cl != null);
 5026      Contract.Requires(currentClass == null);
 5027      Contract.Ensures(currentClass == null);
 8905028      currentClass = cl;
 5029
 592205030      foreach (MemberDecl member in cl.Members) {
 188505031        member.EnclosingClass = cl;
 188505032        if (member is Field) {
 05033          if (member is ConstantField) {
 05034            var m = (ConstantField)member;
 05035            ResolveType(member.tok, ((Field)member).Type, m, ResolveTypeOptionEnum.DontInfer, null);
 05036          } else {
 5037            // In the following, we pass in a NoContext, because any cycle formed by a redirecting-type constraints woul
 5038            // dereference the heap, and such constraints are not allowed to dereference the heap so an error will be pr
 5039            // even if we don't detect this cycle.
 05040            ResolveType(member.tok, ((Field)member).Type, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOption
 05041          }
 325605042        } else if (member is Function) {
 137105043          var f = (Function)member;
 137105044          var ec = reporter.Count(ErrorLevel.Error);
 137105045          allTypeParameters.PushMarker();
 137105046          ResolveTypeParameters(f.TypeArgs, true, f);
 137105047          ResolveFunctionSignature(f);
 137105048          allTypeParameters.PopMarker();
 137105049          if (f is ExtremePredicate && ec == reporter.Count(ErrorLevel.Error)) {
 05050            var ff = ((ExtremePredicate)f).PrefixPredicate;  // note, may be null if there was an error before the prefi
 05051            if (ff != null) {
 05052              ff.EnclosingClass = cl;
 05053              allTypeParameters.PushMarker();
 05054              ResolveTypeParameters(ff.TypeArgs, true, ff);
 05055              ResolveFunctionSignature(ff);
 05056              allTypeParameters.PopMarker();
 05057            }
 05058          }
 137105059          if (f.ByMethodDecl != null) {
 05060            f.ByMethodDecl.EnclosingClass = cl;
 05061          }
 5062
 239905063        } else if (member is Method) {
 51405064          var m = (Method)member;
 51405065          var ec = reporter.Count(ErrorLevel.Error);
 51405066          allTypeParameters.PushMarker();
 51405067          ResolveTypeParameters(m.TypeArgs, true, m);
 51405068          ResolveMethodSignature(m);
 51405069          allTypeParameters.PopMarker();
 51405070          if (m is ExtremeLemma com && com.PrefixLemma != null && ec == reporter.Count(ErrorLevel.Error)) {
 05071            var mm = com.PrefixLemma;
 5072            // resolve signature of the prefix lemma
 05073            mm.EnclosingClass = cl;
 05074            allTypeParameters.PushMarker();
 05075            ResolveTypeParameters(mm.TypeArgs, true, mm);
 05076            ResolveMethodSignature(mm);
 05077            allTypeParameters.PopMarker();
 05078          }
 5079
 51405080        } else {
 05081          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 5082        }
 188505083      }
 5084
 8905085      currentClass = null;
 8905086    }
 5087
 5088    /// <summary>
 5089    /// This method checks the rules for inherited and overridden members. It also populates .InheritedMembers with the
 5090    /// non-static members that are inherited from parent traits.
 5091    /// </summary>
 8905092    void InheritedTraitMembers(TopLevelDeclWithMembers cl) {
 5093      Contract.Requires(cl != null);
 5094      Contract.Requires(cl.ParentTypeInformation != null);
 5095
 592205096      foreach (var member in classMembers[cl].Values) {
 188505097        if (member is PrefixPredicate || member is PrefixLemma) {
 5098          // these are handled with the corresponding extreme predicate/lemma
 05099          continue;
 5100        }
 188505101        if (member.EnclosingClass != cl) {
 5102          // The member is the one inherited from a trait (and the class does not itself define a member with this name)
 5103          // is fine for fields and for functions and methods with bodies. However, if "cl" is not itself a trait, then 
 5104          // or method, "cl" is required to at least redeclare the member with its signature.  (It should also provide a
 5105          // but that will be checked by the verifier.  And it should also have a body, but that will be checked by the 
 05106          if (member.IsStatic) {
 5107            // nothing to do
 05108          } else {
 05109            cl.InheritedMembers.Add(member);
 05110            if (member is Field || (member as Function)?.Body != null || (member as Method)?.Body != null) {
 5111              // member is a field or a fully defined function or method
 05112            } else if (cl is TraitDecl) {
 5113              // there are no expectations that a field needs to repeat the signature of inherited body-less members
 05114            } else if (Attributes.Contains(member.Attributes, "extern")) {
 5115              // Extern functions do not need to be reimplemented.
 5116              // TODO: When `:extern` is separated from `:compile false`, this should become `:compile false`.
 05117            } else if (member is Lemma && Attributes.Contains(member.Attributes, "opaque_reveal")) {
 5118              // reveal lemmas do not need to be reimplemented
 05119            } else {
 05120              reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' does not implement trait {2} '{3}.{4}'", cl.What
 05121            }
 05122          }
 05123          continue;
 5124        }
 377005125        if (member.OverriddenMember == null) {
 5126          // this member has nothing to do with the parent traits
 188505127          continue;
 5128        }
 5129
 05130        var traitMember = member.OverriddenMember;
 05131        var trait = traitMember.EnclosingClass;
 05132        if (traitMember.IsStatic) {
 05133          reporter.Error(MessageSource.Resolver, member.tok, "static {0} '{1}' is inherited from trait '{2}' and is not 
 05134            traitMember.WhatKind, traitMember.Name, trait.Name);
 05135        } else if (member.IsStatic) {
 05136          reporter.Error(MessageSource.Resolver, member.tok, "static member '{0}' overrides non-static member in trait '
 05137        } else if (traitMember is Field) {
 5138          // The class is not allowed to do anything with the field other than silently inherit it.
 05139          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' is inherited from trait '{2}' and is not allowed
 05140        } else if ((traitMember as Function)?.Body != null || (traitMember as Method)?.Body != null) {
 5141          // the overridden member is a fully defined function or method, so the class is not allowed to do anything wit
 05142          reporter.Error(MessageSource.Resolver, member.tok, "fully defined {0} '{1}' is inherited from trait '{2}' and 
 05143            traitMember.WhatKind, traitMember.Name, trait.Name);
 05144        } else if (member is Method != traitMember is Method ||
 05145                   member is Lemma != traitMember is Lemma ||
 05146                   member is TwoStateLemma != traitMember is TwoStateLemma ||
 05147                   member is LeastLemma != traitMember is LeastLemma ||
 05148                   member is GreatestLemma != traitMember is GreatestLemma ||
 05149                   member is Function != traitMember is Function ||
 05150                   member is TwoStateFunction != traitMember is TwoStateFunction ||
 05151                   member is LeastPredicate != traitMember is LeastPredicate ||
 05152                   member is GreatestPredicate != traitMember is GreatestPredicate) {
 05153          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' in '{2}' can only be overridden by a {0} (got {3
 05154        } else if (member.IsGhost != traitMember.IsGhost) {
 05155          reporter.Error(MessageSource.Resolver, member.tok, "overridden {0} '{1}' in '{2}' has different ghost/compiled
 05156            traitMember.WhatKind, traitMember.Name, cl.Name, trait.Name);
 05157        } else {
 5158          // Copy trait member's extern attribute onto class member if class does not provide one
 05159          if (!Attributes.Contains(member.Attributes, "extern") && Attributes.Contains(traitMember.Attributes, "extern")
 05160            var traitExternArgs = Attributes.FindExpressions(traitMember.Attributes, "extern");
 05161            member.Attributes = new Attributes("extern", traitExternArgs, member.Attributes);
 05162          }
 5163
 05164          if (traitMember is Method) {
 05165            var classMethod = (Method)member;
 05166            var traitMethod = (Method)traitMember;
 05167            classMethod.OverriddenMethod = traitMethod;
 5168
 05169            CheckOverride_MethodParameters(classMethod, traitMethod, cl.ParentFormalTypeParametersToActuals);
 5170
 05171            var traitMethodAllowsNonTermination = Contract.Exists(traitMethod.Decreases.Expressions, e => e is WildcardE
 05172            var classMethodAllowsNonTermination = Contract.Exists(classMethod.Decreases.Expressions, e => e is WildcardE
 05173            if (classMethodAllowsNonTermination && !traitMethodAllowsNonTermination) {
 05174              reporter.Error(MessageSource.Resolver, classMethod.tok, "not allowed to override a terminating method with
 05175            }
 5176
 05177          } else if (traitMember is Function) {
 05178            var classFunction = (Function)member;
 05179            var traitFunction = (Function)traitMember;
 05180            classFunction.OverriddenFunction = traitFunction;
 5181
 05182            CheckOverride_FunctionParameters(classFunction, traitFunction, cl.ParentFormalTypeParametersToActuals);
 5183
 05184          } else {
 05185            Contract.Assert(false); // unexpected member
 05186          }
 05187        }
 05188      }
 8905189    }
 5190
 05191    public void CheckOverride_FunctionParameters(Function nw, Function old, Dictionary<TypeParameter, Type> classTypeMap
 5192      Contract.Requires(nw != null);
 5193      Contract.Requires(old != null);
 5194      Contract.Requires(classTypeMap != null);
 5195
 05196      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "function", classTypeMap);
 05197      if (nw is ExtremePredicate nwFix && old is ExtremePredicate oldFix && nwFix.KNat != oldFix.KNat) {
 05198        reporter.Error(MessageSource.Resolver, nw,
 05199          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05200          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05201      }
 05202      CheckOverride_ResolvedParameters(nw.tok, old.Formals, nw.Formals, nw.Name, "function", "parameter", typeMap);
 05203      var oldResultType = old.ResultType.Subst(typeMap);
 05204      if (!nw.ResultType.Equals(oldResultType, true)) {
 05205        reporter.Error(MessageSource.Resolver, nw, "the result type of function '{0}' ({1}) differs from that in the ove
 05206          nw.Name, nw.ResultType, oldResultType);
 05207      }
 05208    }
 5209
 05210    public void CheckOverride_MethodParameters(Method nw, Method old, Dictionary<TypeParameter, Type> classTypeMap) {
 5211      Contract.Requires(nw != null);
 5212      Contract.Requires(old != null);
 5213      Contract.Requires(classTypeMap != null);
 05214      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "method", classTypeMap);
 05215      if (nw is ExtremeLemma nwFix && old is ExtremeLemma oldFix && nwFix.KNat != oldFix.KNat) {
 05216        reporter.Error(MessageSource.Resolver, nw,
 05217          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05218          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05219      }
 05220      CheckOverride_ResolvedParameters(nw.tok, old.Ins, nw.Ins, nw.Name, "method", "in-parameter", typeMap);
 05221      CheckOverride_ResolvedParameters(nw.tok, old.Outs, nw.Outs, nw.Name, "method", "out-parameter", typeMap);
 05222    }
 5223
 05224    private Dictionary<TypeParameter, Type> CheckOverride_TypeParameters(IToken tok, List<TypeParameter> old, List<TypeP
 5225      Contract.Requires(tok != null);
 5226      Contract.Requires(old != null);
 5227      Contract.Requires(nw != null);
 5228      Contract.Requires(name != null);
 5229      Contract.Requires(thing != null);
 05230      var typeMap = old.Count == 0 ? classTypeMap : new Dictionary<TypeParameter, Type>(classTypeMap);
 05231      if (old.Count != nw.Count) {
 05232        reporter.Error(MessageSource.Resolver, tok,
 05233          "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than in the overridden 
 05234      } else {
 05235        for (int i = 0; i < old.Count; i++) {
 05236          var o = old[i];
 05237          var n = nw[i];
 05238          typeMap.Add(o, new UserDefinedType(tok, n));
 5239          // Check type characteristics
 05240          if (o.Characteristics.EqualitySupport != TypeParameter.EqualitySupportValue.InferredRequired && o.Characterist
 05241            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05242          }
 05243          if (o.Characteristics.HasCompiledValue != n.Characteristics.HasCompiledValue) {
 05244            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05245          } else if (o.Characteristics.IsNonempty != n.Characteristics.IsNonempty) {
 05246            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05247          }
 05248          if (o.Characteristics.ContainsNoReferenceTypes != n.Characteristics.ContainsNoReferenceTypes) {
 05249            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the no-referenc
 05250          }
 5251
 05252        }
 05253      }
 05254      return typeMap;
 05255    }
 5256
 05257    private void CheckOverride_ResolvedParameters(IToken tok, List<Formal> old, List<Formal> nw, string name, string thi
 5258      Contract.Requires(tok != null);
 5259      Contract.Requires(old != null);
 5260      Contract.Requires(nw != null);
 5261      Contract.Requires(name != null);
 5262      Contract.Requires(thing != null);
 5263      Contract.Requires(parameterKind != null);
 5264      Contract.Requires(typeMap != null);
 05265      if (old.Count != nw.Count) {
 05266        reporter.Error(MessageSource.Resolver, tok, "{0} '{1}' is declared with a different number of {2} ({3} instead o
 05267          thing, name, parameterKind, nw.Count, old.Count);
 05268      } else {
 05269        for (int i = 0; i < old.Count; i++) {
 05270          var o = old[i];
 05271          var n = nw[i];
 05272          if (!o.IsGhost && n.IsGhost) {
 05273            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05274              parameterKind, n.Name, thing, name);
 05275          } else if (o.IsGhost && !n.IsGhost) {
 05276            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05277              parameterKind, n.Name, thing, name);
 05278          } else if (!o.IsOld && n.IsOld) {
 05279            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05280              parameterKind, n.Name, thing, name);
 05281          } else if (o.IsOld && !n.IsOld) {
 05282            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05283              parameterKind, n.Name, thing, name);
 05284          } else if (!o.IsOlder && n.IsOlder) {
 05285            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05286              parameterKind, n.Name, thing, name);
 05287          } else if (o.IsOlder && !n.IsOlder) {
 05288            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05289              parameterKind, n.Name, thing, name);
 05290          } else {
 05291            var oo = o.Type.Subst(typeMap);
 05292            if (!n.Type.Equals(oo, true)) {
 05293              reporter.Error(MessageSource.Resolver, n.tok,
 05294                "the type of {0} '{1}' is different from the type of the corresponding {0} in trait {2} ('{3}' instead o
 05295                parameterKind, n.Name, thing, n.Type, oo);
 05296            }
 05297          }
 05298        }
 05299      }
 05300    }
 5301
 5302    /// <summary>
 5303    /// Check that the SCC of 'startingPoint' can be carved up into stratospheres in such a way that each
 5304    /// datatype has some value that can be constructed from datatypes in lower stratospheres only.
 5305    /// The algorithm used here is quadratic in the number of datatypes in the SCC.  Since that number is
 5306    /// deemed to be rather small, this seems okay.
 5307    ///
 5308    /// As a side effect of this checking, the GroundingCtor field is filled in (for every inductive datatype
 5309    /// that passes the check).  It may be that several constructors could be used as the default, but
 5310    /// only the first one encountered as recorded.  This particular choice is slightly more than an
 5311    /// implementation detail, because it affects how certain cycles among inductive datatypes (having
 5312    /// to do with the types used to instantiate type parameters of datatypes) are used.
 5313    ///
 5314    /// The role of the SCC here is simply to speed up this method.  It would still be correct if the
 5315    /// equivalence classes in the given SCC were unions of actual SCC's.  In particular, this method
 5316    /// would still work if "dependencies" consisted of one large SCC containing all the inductive
 5317    /// datatypes in the module.
 5318    /// </summary>
 05319    void SccStratosphereCheck(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5320      Contract.Requires(startingPoint != null);
 5321      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5322
 05323      var scc = dependencies.GetSCC(startingPoint);
 05324      int totalCleared = 0;
 05325      while (true) {
 05326        int clearedThisRound = 0;
 05327        foreach (var dt in scc) {
 05328          if (dt.GroundingCtor != null) {
 5329            // previously cleared
 05330          } else if (ComputeGroundingCtor(dt)) {
 05331            Contract.Assert(dt.GroundingCtor != null);  // should have been set by the successful call to StratosphereCh
 05332            clearedThisRound++;
 05333            totalCleared++;
 05334          }
 05335        }
 05336        if (totalCleared == scc.Count) {
 5337          // all is good
 05338          return;
 05339        } else if (clearedThisRound != 0) {
 5340          // some progress was made, so let's keep going
 05341        } else {
 5342          // whatever is in scc-cleared now failed to pass the test
 05343          foreach (var dt in scc) {
 05344            if (dt.GroundingCtor == null) {
 05345              reporter.Error(MessageSource.Resolver, dt, "because of cyclic dependencies among constructor argument type
 05346            }
 05347          }
 05348          return;
 5349        }
 05350      }
 05351    }
 5352
 5353    /// <summary>
 5354    /// Check that the datatype has some constructor all whose argument types can be constructed.
 5355    /// Returns 'true' and sets dt.GroundingCtor if that is the case.
 5356    /// </summary>
 05357    bool ComputeGroundingCtor(IndDatatypeDecl dt) {
 5358      Contract.Requires(dt != null);
 5359      Contract.Requires(dt.GroundingCtor == null);  // the intention is that this method be called only when GroundingCt
 5360      Contract.Ensures(!Contract.Result<bool>() || dt.GroundingCtor != null);
 5361
 5362      // Stated differently, check that there is some constuctor where no argument type goes to the same stratum.
 05363      DatatypeCtor groundingCtor = null;
 05364      ISet<TypeParameter> lastTypeParametersUsed = null;
 05365      foreach (DatatypeCtor ctor in dt.Ctors) {
 05366        var typeParametersUsed = new HashSet<TypeParameter>();
 05367        foreach (Formal p in ctor.Formals) {
 05368          if (!CheckCanBeConstructed(p.Type, typeParametersUsed)) {
 5369            // the argument type (has a component which) is not yet known to be constructable
 05370            goto NEXT_OUTER_ITERATION;
 5371          }
 05372        }
 5373        // this constructor satisfies the requirements, check to see if it is a better fit than the
 5374        // one found so far. Here, "better" means
 5375        //   * a ghost constructor is better than a non-ghost constructor
 5376        //   * among those, a constructor with fewer type arguments is better
 5377        //   * among those, the first one is preferred.
 05378        if (groundingCtor == null || (!groundingCtor.IsGhost && ctor.IsGhost) || typeParametersUsed.Count < lastTypePara
 05379          groundingCtor = ctor;
 05380          lastTypeParametersUsed = typeParametersUsed;
 05381        }
 5382
 05383      NEXT_OUTER_ITERATION: { }
 05384      }
 5385
 05386      if (groundingCtor != null) {
 05387        dt.GroundingCtor = groundingCtor;
 05388        dt.TypeParametersUsedInConstructionByGroundingCtor = new bool[dt.TypeArgs.Count];
 05389        for (int i = 0; i < dt.TypeArgs.Count; i++) {
 05390          dt.TypeParametersUsedInConstructionByGroundingCtor[i] = lastTypeParametersUsed.Contains(dt.TypeArgs[i]);
 05391        }
 05392        return true;
 5393      }
 5394
 5395      // no constructor satisfied the requirements, so this is an illegal datatype declaration
 05396      return false;
 05397    }
 5398
 05399    bool CheckCanBeConstructed(Type type, ISet<TypeParameter> typeParametersUsed) {
 05400      type = type.NormalizeExpandKeepConstraints();
 05401      if (type is BasicType) {
 5402        // values of primitive types can always be constructed
 05403        return true;
 05404      } else if (type is CollectionType) {
 5405        // values of collection types can always be constructed
 05406        return true;
 5407      }
 5408
 05409      var udt = (UserDefinedType)type;
 05410      var cl = udt.ResolvedClass;
 05411      Contract.Assert(cl != null);
 05412      if (cl is TypeParameter) {
 5413        // treat a type parameter like a ground type
 05414        typeParametersUsed.Add((TypeParameter)cl);
 05415        return true;
 05416      } else if (cl is AbstractTypeDecl) {
 5417        // an opaque is like a ground type
 05418        return true;
 05419      } else if (cl is InternalTypeSynonymDecl) {
 5420        // a type exported as opaque from another module is like a ground type
 05421        return true;
 05422      } else if (cl is NewtypeDecl) {
 5423        // values of a newtype can be constructed
 05424        return true;
 05425      } else if (cl is SubsetTypeDecl) {
 05426        var td = (SubsetTypeDecl)cl;
 05427        if (td.Witness != null) {
 5428          // a witness exists, but may depend on type parameters
 05429          type.AddFreeTypeParameters(typeParametersUsed);
 05430          return true;
 05431        } else if (td.WitnessKind == SubsetTypeDecl.WKind.Special) {
 5432          // WKind.Special is only used with -->, ->, and non-null types:
 05433          Contract.Assert(ArrowType.IsPartialArrowTypeName(td.Name) || ArrowType.IsTotalArrowTypeName(td.Name) || td is 
 05434          if (ArrowType.IsTotalArrowTypeName(td.Name)) {
 05435            return CheckCanBeConstructed(udt.TypeArgs.Last(), typeParametersUsed);
 05436          } else {
 05437            return true;
 5438          }
 05439        } else {
 05440          return CheckCanBeConstructed(td.RhsWithArgument(udt.TypeArgs), typeParametersUsed);
 5441        }
 05442      } else if (cl is ClassDecl) {
 5443        // null is a value for this possibly-null type
 05444        return true;
 05445      } else if (cl is CoDatatypeDecl) {
 5446        // may depend on type parameters
 05447        type.AddFreeTypeParameters(typeParametersUsed);
 05448        return true;
 5449      }
 5450
 05451      var dependee = type.AsIndDatatype;
 05452      Contract.Assert(dependee != null);
 05453      if (dependee.GroundingCtor == null) {
 5454        // the type is an inductive datatype that we don't yet know how to construct
 05455        return false;
 5456      }
 5457      // also check the type arguments of the inductive datatype
 05458      Contract.Assert(udt.TypeArgs.Count == dependee.TypeParametersUsedInConstructionByGroundingCtor.Length);
 05459      var i = 0;
 05460      foreach (var ta in udt.TypeArgs) {
 05461        if (dependee.TypeParametersUsedInConstructionByGroundingCtor[i] && !CheckCanBeConstructed(ta, typeParametersUsed
 05462          return false;
 5463        }
 05464        i++;
 05465      }
 05466      return true;
 05467    }
 5468
 05469    void DetermineEqualitySupport(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5470      Contract.Requires(startingPoint != null);
 5471      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5472
 05473      var scc = dependencies.GetSCC(startingPoint);
 5474
 05475      void MarkSCCAsNotSupportingEquality() {
 05476        foreach (var ddtt in scc) {
 05477          ddtt.EqualitySupport = IndDatatypeDecl.ES.Never;
 05478        }
 05479      }
 5480
 5481      // Look for conditions that make the whole SCC incapable of providing the equality operation:
 5482      //   * a datatype in the SCC has a ghost constructor
 5483      //   * a parameter of an inductive datatype in the SCC is ghost
 5484      //   * the type of a parameter of an inductive datatype in the SCC does not support equality
 05485      foreach (var dt in scc) {
 05486        Contract.Assume(dt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed);
 05487        foreach (var ctor in dt.Ctors) {
 05488          if (ctor.IsGhost) {
 05489            MarkSCCAsNotSupportingEquality();
 05490            return;  // we are done
 5491          }
 05492          foreach (var arg in ctor.Formals) {
 05493            var anotherIndDt = arg.Type.AsIndDatatype;
 05494            if (arg.IsGhost ||
 05495                (anotherIndDt != null && anotherIndDt.EqualitySupport == IndDatatypeDecl.ES.Never) ||
 05496                arg.Type.IsCoDatatype ||
 05497                arg.Type.IsArrowType) {
 5498              // arg.Type is known never to support equality
 05499              MarkSCCAsNotSupportingEquality();
 05500              return;  // we are done
 5501            }
 05502          }
 05503        }
 05504      }
 5505
 5506      // Now for the more involved case:  we need to determine which type parameters determine equality support for each
 5507      // We start by seeing where each datatype's type parameters are used in a place known to determine equality suppor
 05508      bool thingsChanged = false;
 05509      foreach (var dt in scc) {
 05510        if (dt.TypeArgs.Count == 0) {
 5511          // if the datatype has no type parameters, we certainly won't find any type parameters being used in the argum
 05512          continue;
 5513        }
 05514        foreach (var ctor in dt.Ctors) {
 05515          foreach (var arg in ctor.Formals) {
 05516            var typeArg = arg.Type.AsTypeParameter;
 05517            if (typeArg != null) {
 05518              typeArg.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05519              thingsChanged = true;
 05520            } else {
 05521              var otherDt = arg.Type.AsIndDatatype;
 05522              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.ConsultTypeArguments) {  // datatype 
 05523                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05524                var i = 0;
 05525                foreach (var otherTp in otherDt.TypeArgs) {
 05526                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05527                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05528                    if (tp != null) {
 05529                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05530                      thingsChanged = true;
 05531                    }
 05532                  }
 05533                }
 05534              }
 05535            }
 05536          }
 05537        }
 05538      }
 5539      // Then we propagate this information up through the SCC
 05540      while (thingsChanged) {
 05541        thingsChanged = false;
 05542        foreach (var dt in scc) {
 05543          if (dt.TypeArgs.Count == 0) {
 5544            // if the datatype has no type parameters, we certainly won't find any type parameters being used in the arg
 05545            continue;
 5546          }
 05547          foreach (var ctor in dt.Ctors) {
 05548            foreach (var arg in ctor.Formals) {
 05549              var otherDt = arg.Type.AsIndDatatype;
 05550              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed) { // otherDt lives in
 05551                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05552                var i = 0;
 05553                foreach (var otherTp in otherDt.TypeArgs) {
 05554                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05555                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05556                    if (tp != null && !tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05557                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05558                      thingsChanged = true;
 05559                    }
 05560                  }
 05561                  i++;
 05562                }
 05563              }
 05564            }
 05565          }
 05566        }
 05567      }
 5568      // Now that we have computed the .NecessaryForEqualitySupportOfSurroundingInductiveDatatype values, mark the datat
 5569      // where equality support should be checked by looking at the type arguments.
 05570      foreach (var dt in scc) {
 05571        dt.EqualitySupport = IndDatatypeDecl.ES.ConsultTypeArguments;
 05572      }
 05573    }
 5574
 5575    /// <summary>
 5576    /// Check to see if the attribute is one that is supported by Dafny.  What check performed here is,
 5577    /// unfortunately, just an approximation, since the usage rules of a particular attribute is checked
 5578    /// elsewhere (for example, in the compiler or verifier).  It would be nice to improve this.
 5579    /// </summary>
 05580    bool IsRecognizedAttribute(UserSuppliedAttributes a, IAttributeBearingDeclaration host) {
 5581      Contract.Requires(a != null);
 5582      Contract.Requires(host != null);
 05583      switch (a.Name) {
 5584        case "opaque":
 05585          return host is Function && !(host is ExtremePredicate);
 5586        case "trigger":
 05587          return host is ComprehensionExpr || host is SetComprehension || host is MapComprehension;
 5588        case "timeLimit":
 5589        case "timeLimitMultiplier":
 05590          return host is TopLevelDecl;
 5591        case "tailrecursive":
 05592          return host is Method && !((Method)host).IsGhost;
 5593        case "autocontracts":
 05594          return host is ClassDecl;
 5595        case "autoreq":
 05596          return host is Function;
 5597        case "abstemious":
 05598          return host is Function;
 5599        case "options":
 05600          return host is ModuleDefinition;
 5601        default:
 05602          return false;
 5603      }
 05604    }
 5605
 4481405606    public void ScopePushAndReport(Scope<IVariable> scope, IVariable v, string kind) {
 5607      Contract.Requires(scope != null);
 5608      Contract.Requires(v != null);
 5609      Contract.Requires(kind != null);
 4481405610      ScopePushAndReport(scope, v.Name, v, v.Tok, kind);
 4481405611    }
 5612
 4481405613    void ScopePushAndReport<Thing>(Scope<Thing> scope, string name, Thing thing, IToken tok, string kind) where Thing : 
 5614      Contract.Requires(scope != null);
 5615      Contract.Requires(name != null);
 5616      Contract.Requires(thing != null);
 5617      Contract.Requires(tok != null);
 5618      Contract.Requires(kind != null);
 4481405619      var r = scope.Push(name, thing);
 4481405620      switch (r) {
 5621        case Scope<Thing>.PushResult.Success:
 4481405622          break;
 5623        case Scope<Thing>.PushResult.Duplicate:
 05624          reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Duplicate {0} name: {1}", kind, name);
 05625          break;
 5626        case Scope<Thing>.PushResult.Shadow:
 05627          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Shadowed {0} name: {1}", kind, name);
 05628          break;
 5629      }
 4481405630    }
 5631
 5632    /// <summary>
 5633    /// Assumes type parameters have already been pushed
 5634    /// </summary>
 146005635    void ResolveFunctionSignature(Function f) {
 5636      Contract.Requires(f != null);
 146005637      scope.PushMarker();
 146005638      if (f.SignatureIsOmitted) {
 05639        reporter.Error(MessageSource.Resolver, f, "function signature can be omitted only in refining functions");
 05640      }
 146005641      var option = f.TypeArgs.Count == 0 ? new ResolveTypeOption(f) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 1517105642      foreach (Formal p in f.Formals) {
 359705643        ScopePushAndReport(scope, p, "parameter");
 359705644        ResolveType(p.tok, p.Type, f, option, f.TypeArgs);
 359705645      }
 146005646      if (f.Result != null) {
 05647        ScopePushAndReport(scope, f.Result, "parameter/return");
 05648        ResolveType(f.Result.tok, f.Result.Type, f, option, f.TypeArgs);
 146005649      } else {
 146005650        ResolveType(f.tok, f.ResultType, f, option, f.TypeArgs);
 146005651      }
 146005652      scope.PopMarker();
 146005653    }
 5654
 5655    /// <summary>
 5656    /// This method can be called even if the resolution of "fe" failed; in that case, this method will
 5657    /// not issue any error message.
 5658    /// </summary>
 05659    public void DisallowNonGhostFieldSpecifiers(FrameExpression fe) {
 5660      Contract.Requires(fe != null);
 05661      if (fe.Field != null && !fe.Field.IsGhost) {
 05662        reporter.Error(MessageSource.Resolver, fe.E, "in a ghost context, only ghost fields can be mentioned as modifies
 05663      }
 05664    }
 5665
 5666    /// <summary>
 5667    /// Assumes type parameters have already been pushed
 5668    /// </summary>
 51405669    void ResolveMethodSignature(Method m) {
 5670      Contract.Requires(m != null);
 5671
 51405672      scope.PushMarker();
 51405673      if (m.SignatureIsOmitted) {
 05674        reporter.Error(MessageSource.Resolver, m, "method signature can be omitted only in refining methods");
 05675      }
 51405676      var option = m.TypeArgs.Count == 0 ? new ResolveTypeOption(m) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 5677      // resolve in-parameters
 480305678      foreach (Formal p in m.Ins) {
 108705679        ScopePushAndReport(scope, p, "parameter");
 108705680        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 108705681      }
 5682      // resolve out-parameters
 345305683      foreach (Formal p in m.Outs) {
 63705684        ScopePushAndReport(scope, p, "parameter");
 63705685        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 63705686      }
 51405687      scope.PopMarker();
 51405688    }
 5689
 5690    /// <summary>
 5691    /// Assumes type parameters have already been pushed
 5692    /// </summary>
 05693    void ResolveIteratorSignature(IteratorDecl iter) {
 5694      Contract.Requires(iter != null);
 05695      scope.PushMarker();
 05696      if (iter.SignatureIsOmitted) {
 05697        reporter.Error(MessageSource.Resolver, iter, "iterator signature can be omitted only in refining methods");
 05698      }
 05699      var initiallyNoTypeArguments = iter.TypeArgs.Count == 0;
 05700      var option = initiallyNoTypeArguments ? new ResolveTypeOption(iter) : new ResolveTypeOption(ResolveTypeOptionEnum.
 5701      // resolve the types of the parameters
 05702      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 05703      foreach (var p in iter.Ins) {
 05704        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05705      }
 05706      foreach (var p in iter.Outs) {
 05707        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05708        if (!p.Type.KnownToHaveToAValue(p.IsGhost)) {
 05709          reporter.Error(MessageSource.Resolver, p.tok, "type of yield-parameter must support auto-initialization (got '
 05710        }
 05711      }
 5712      // resolve the types of the added fields (in case some of these types would cause the addition of default type arg
 05713      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05714        foreach (var p in iter.OutsHistoryFields) {
 05715          ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05716        }
 05717      }
 05718      if (iter.TypeArgs.Count != iter.NonNullTypeDecl.TypeArgs.Count) {
 5719        // Apparently, the type resolution automatically added type arguments to the iterator. We'll add these to the
 5720        // corresponding non-null type as well.
 05721        Contract.Assert(initiallyNoTypeArguments);
 05722        Contract.Assert(iter.NonNullTypeDecl.TypeArgs.Count == 0);
 05723        var nnt = iter.NonNullTypeDecl;
 05724        nnt.TypeArgs.AddRange(iter.TypeArgs.ConvertAll(tp => new TypeParameter(tp.RangeToken, tp.NameNode, tp.VarianceSy
 05725        var varUdt = (UserDefinedType)nnt.Var.Type;
 05726        Contract.Assert(varUdt.TypeArgs.Count == 0);
 05727        varUdt.TypeArgs = nnt.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 05728      }
 05729      scope.PopMarker();
 05730    }
 5731
 5732    // Like the ResolveTypeOptionEnum, but iff the case of AllowPrefixExtend, it also
 5733    // contains a pointer to its Parent class, to fill in default type parameters properly.
 5734    public class ResolveTypeOption {
 5735      public readonly ResolveTypeOptionEnum Opt;
 5736      public readonly TypeParameter.ParentType Parent;
 5737      [ContractInvariantMethod]
 05738      void ObjectInvariant() {
 5739        Contract.Invariant((Opt == ResolveTypeOptionEnum.AllowPrefixExtend) == (Parent != null));
 05740      }
 5741
 9349805742      public ResolveTypeOption(ResolveTypeOptionEnum opt) {
 5743        Contract.Requires(opt != ResolveTypeOptionEnum.AllowPrefixExtend);
 4674905744        Parent = null;
 4674905745        Opt = opt;
 4674905746      }
 5747
 234605748      public ResolveTypeOption(TypeParameter.ParentType parent) {
 5749        Contract.Requires(parent != null);
 117305750        Opt = ResolveTypeOptionEnum.AllowPrefixExtend;
 117305751        Parent = parent;
 117305752      }
 5753    }
 5754
 5755    /// <summary>
 5756    /// Returns a resolved type denoting an array type with dimension "dims" and element type "arg".
 5757    /// Callers are expected to provide "arg" as an already resolved type.  (Note, a proxy type is resolved--
 5758    /// only types that contain identifiers stand the possibility of not being resolved.)
 5759    /// </summary>
 05760    Type ResolvedArrayType(IToken tok, int dims, Type arg, ResolutionContext resolutionContext, bool useClassNameType) {
 5761      Contract.Requires(tok != null);
 5762      Contract.Requires(1 <= dims);
 5763      Contract.Requires(arg != null);
 05764      var at = builtIns.ArrayType(tok, dims, new List<Type> { arg }, false, useClassNameType);
 05765      ResolveType(tok, at, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 05766      return at;
 05767    }
 5768
 05769    void FillInDefaultLoopDecreases(LoopStmt loopStmt, Expression guard, List<Expression> theDecreases, ICallable enclos
 5770      Contract.Requires(loopStmt != null);
 5771      Contract.Requires(theDecreases != null);
 5772
 05773      if (theDecreases.Count == 0 && guard != null) {
 05774        loopStmt.InferredDecreases = true;
 05775        Expression prefix = null;
 05776        foreach (Expression guardConjunct in Expression.Conjuncts(guard)) {
 05777          Expression guess = null;
 05778          var neutralValue = Expression.CreateIntLiteral(guardConjunct.tok, -1);
 05779          if (guardConjunct is BinaryExpr bin) {
 05780            switch (bin.ResolvedOp) {
 5781              case BinaryExpr.ResolvedOpcode.Lt:
 5782              case BinaryExpr.ResolvedOpcode.Le:
 5783              case BinaryExpr.ResolvedOpcode.LtChar:
 5784              case BinaryExpr.ResolvedOpcode.LeChar:
 05785                if (bin.E0.Type.IsBigOrdinalType) {
 5786                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05787                  guess = bin.E1;
 05788                } else {
 5789                  // for A < B and A <= B, use the decreases B - A
 05790                  guess = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05791                }
 05792                break;
 5793              case BinaryExpr.ResolvedOpcode.Ge:
 5794              case BinaryExpr.ResolvedOpcode.Gt:
 5795              case BinaryExpr.ResolvedOpcode.GeChar:
 5796              case BinaryExpr.ResolvedOpcode.GtChar:
 05797                if (bin.E0.Type.IsBigOrdinalType) {
 5798                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05799                  guess = bin.E0;
 05800                } else {
 5801                  // for A >= B and A > B, use the decreases A - B
 05802                  guess = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05803                }
 05804                break;
 5805              case BinaryExpr.ResolvedOpcode.ProperSubset:
 5806              case BinaryExpr.ResolvedOpcode.Subset:
 05807                if (bin.E0.Type.AsSetType.Finite) {
 5808                  // for A < B and A <= B, use the decreases |B - A|
 05809                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05810                }
 05811                break;
 5812              case BinaryExpr.ResolvedOpcode.Superset:
 5813              case BinaryExpr.ResolvedOpcode.ProperSuperset:
 05814                if (bin.E0.Type.AsSetType.Finite) {
 5815                  // for A >= B and A > B, use the decreases |A - B|
 05816                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05817                }
 05818                break;
 5819              case BinaryExpr.ResolvedOpcode.ProperMultiSubset:
 5820              case BinaryExpr.ResolvedOpcode.MultiSubset:
 5821                // for A < B and A <= B, use the decreases |B - A|
 05822                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05823                break;
 5824              case BinaryExpr.ResolvedOpcode.MultiSuperset:
 5825              case BinaryExpr.ResolvedOpcode.ProperMultiSuperset:
 5826                // for A >= B and A > B, use the decreases |A - B|
 05827                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05828                break;
 5829              case BinaryExpr.ResolvedOpcode.Prefix:
 5830              case BinaryExpr.ResolvedOpcode.ProperPrefix:
 5831                // for "[] < B" and "[] <= B", use B
 05832                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05833                  guess = bin.E1;
 05834                }
 05835                break;
 5836              case BinaryExpr.ResolvedOpcode.NeqCommon:
 05837                if (bin.E0.Type.IsNumericBased() || bin.E0.Type.IsBitVectorType || bin.E0.Type.IsCharType) {
 5838                  // for A != B where A and B are numeric, use the absolute difference between A and B (that is: if A <=
 05839                  var AminusB = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05840                  var BminusA = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05841                  var test = Expression.CreateAtMost(bin.E0, bin.E1);
 05842                  guess = Expression.CreateITE(test, BminusA, AminusB);
 05843                } else if (bin.E0.Type.IsBigOrdinalType) {
 5844                  // if either of the operands is a literal, pick the other; otherwise, don't make any guess
 05845                  if (Expression.StripParens(bin.E0) is LiteralExpr) {
 05846                    guess = bin.E1;
 05847                  } else if (Expression.StripParens(bin.E1) is LiteralExpr) {
 05848                    guess = bin.E0;
 05849                  }
 05850                }
 05851                break;
 5852              case BinaryExpr.ResolvedOpcode.SetNeq:
 05853                if (bin.E0.Type.AsSetType.Finite) {
 5854                  // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty set
 05855                  if (LiteralExpr.IsEmptySet(bin.E0)) {
 05856                    guess = bin.E1;
 05857                  } else if (LiteralExpr.IsEmptySet(bin.E1)) {
 05858                    guess = bin.E0;
 05859                  } else {
 05860                    var x = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05861                    var y = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05862                    guess = Expression.CreateAdd(x, y);
 05863                  }
 05864                }
 05865                break;
 5866              case BinaryExpr.ResolvedOpcode.MultiSetNeq:
 5867                // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty multiset
 05868                if (LiteralExpr.IsEmptyMultiset(bin.E0)) {
 05869                  guess = bin.E1;
 05870                } else if (LiteralExpr.IsEmptyMultiset(bin.E1)) {
 05871                  guess = bin.E0;
 05872                } else {
 05873                  var x = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05874                  var y = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05875                  guess = Expression.CreateAdd(x, y);
 05876                }
 05877                break;
 5878              case BinaryExpr.ResolvedOpcode.SeqNeq:
 5879                // if either operand is [], then use the other
 05880                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05881                  guess = bin.E1;
 05882                } else if (LiteralExpr.IsEmptySequence(bin.E1)) {
 05883                  guess = bin.E0;
 05884                }
 05885                break;
 5886              default:
 05887                break;
 5888            }
 05889            if (bin.E0.Type.AsSetType != null) {
 05890              neutralValue = new SetDisplayExpr(bin.tok, bin.E0.Type.AsSetType.Finite, new List<Expression>()) {
 05891                Type = bin.E0.Type.NormalizeExpand()
 05892              };
 05893            } else if (bin.E0.Type.AsMultiSetType != null) {
 05894              neutralValue = new MultiSetDisplayExpr(bin.tok, new List<Expression>()) {
 05895                Type = bin.E0.Type.NormalizeExpand()
 05896              };
 05897            } else if (bin.E0.Type.AsSeqType != null) {
 05898              neutralValue = new SeqDisplayExpr(bin.tok, new List<Expression>()) {
 05899                Type = bin.E0.Type.NormalizeExpand()
 05900              };
 05901            } else if (bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 05902              neutralValue = Expression.CreateRealLiteral(bin.tok, BaseTypes.BigDec.FromInt(-1));
 05903            }
 05904          }
 05905          if (guess != null) {
 05906            if (prefix != null) {
 5907              // Make the following guess:  if prefix then guess else neutralValue
 05908              guess = Expression.CreateITE(prefix, guess, neutralValue);
 05909            }
 05910            theDecreases.Add(AutoGeneratedExpression.Create(guess));
 05911          }
 05912          if (prefix == null) {
 05913            prefix = guardConjunct;
 05914          } else {
 05915            prefix = Expression.CreateAnd(prefix, guardConjunct);
 05916          }
 05917        }
 05918      }
 05919      if (enclosingMethod is IteratorDecl) {
 05920        var iter = (IteratorDecl)enclosingMethod;
 05921        var ie = new IdentifierExpr(loopStmt.Tok, iter.YieldCountVariable.Name);
 05922        ie.Var = iter.YieldCountVariable;  // resolve here
 05923        ie.Type = iter.YieldCountVariable.Type;  // resolve here
 05924        theDecreases.Insert(0, AutoGeneratedExpression.Create(ie));
 05925        loopStmt.InferredDecreases = true;
 05926      }
 05927      if (loopStmt.InferredDecreases && theDecreases.Count != 0) {
 05928        string s = "decreases " + Util.Comma(theDecreases, expr => Printer.ExprToString(Options, expr));
 05929        reporter.Info(MessageSource.Resolver, loopStmt.Tok, s);
 05930      }
 05931    }
 5932
 05933    public Expression VarDotMethod(IToken tok, string varname, string methodname) {
 05934      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), methodname, null), new Li
 05935    }
 5936
 05937    public Expression makeTemp(String prefix, AssignOrReturnStmt s, ResolutionContext resolutionContext, Expression ex) 
 05938      var temp = FreshTempVarName(prefix, resolutionContext.CodeContext);
 05939      var locvar = new LocalVariable(s.RangeToken, temp, ex.Type, false);
 05940      var id = new IdentifierExpr(s.Tok, temp);
 05941      var idlist = new List<Expression>() { id };
 05942      var lhss = new List<LocalVariable>() { locvar };
 05943      var rhss = new List<AssignmentRhs>() { new ExprRhs(ex) };
 05944      var up = new UpdateStmt(s.RangeToken, idlist, rhss);
 05945      s.ResolvedStatements.Add(new VarDeclStmt(s.RangeToken, lhss, up));
 05946      return id;
 05947    }
 5948
 05949    public void EnsureSupportsErrorHandling(IToken tok, Type tp, bool expectExtract, bool hasKeywordToken) {
 5950      // The "method not found" errors which will be generated here were already reported while
 5951      // resolving the statement, so we don't want them to reappear and redirect them into a sink.
 05952      var origReporter = this.reporter;
 05953      this.reporter = new ErrorReporterSink(Options, origReporter.OuterModule);
 5954
 05955      var isFailure = ResolveMember(tok, tp, "IsFailure", out _);
 05956      var propagateFailure = ResolveMember(tok, tp, "PropagateFailure", out _);
 05957      var extract = ResolveMember(tok, tp, "Extract", out _);
 5958
 05959      if (hasKeywordToken) {
 05960        if (isFailure == null || (extract != null) != expectExtract) {
 5961          // more details regarding which methods are missing have already been reported by regular resolution
 05962          origReporter.Error(MessageSource.Resolver, tok,
 05963            "The right-hand side of ':-', which is of type '{0}', with a keyword token must have function{1}", tp,
 05964            expectExtract
 05965              ? "s 'IsFailure()' and 'Extract()'"
 05966              : " 'IsFailure()', but not 'Extract()'");
 05967        }
 05968      } else {
 05969        if (isFailure == null || propagateFailure == null || (extract != null) != expectExtract) {
 5970          // more details regarding which methods are missing have already been reported by regular resolution
 05971          origReporter.Error(MessageSource.Resolver, tok,
 05972            "The right-hand side of ':-', which is of type '{0}', must have function{1}", tp,
 05973            expectExtract
 05974              ? "s 'IsFailure()', 'PropagateFailure()', and 'Extract()'"
 05975              : "s 'IsFailure()' and 'PropagateFailure()', but not 'Extract()'");
 05976        }
 05977      }
 5978
 05979      void checkIsFunction([CanBeNull] MemberDecl memberDecl, bool allowMethod) {
 05980        if (memberDecl == null || memberDecl is Function) {
 5981          // fine
 05982        } else if (allowMethod && memberDecl is Method) {
 5983          // give a deprecation warning, so we will remove this language feature around the Dafny 4 time frame
 05984          origReporter.Deprecated(MessageSource.Resolver, ErrorRegistry.NoneId, tok,
 05985            $"Support for member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) being a method 
 05986            " declare it to be a function instead");
 05987        } else {
 5988          // not allowed
 05989          origReporter.Error(MessageSource.Resolver, tok,
 05990            $"Member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) is expected to be a functio
 05991        }
 05992      }
 5993
 05994      checkIsFunction(isFailure, false);
 05995      if (!hasKeywordToken) {
 05996        checkIsFunction(propagateFailure, true);
 05997      }
 05998      if (expectExtract) {
 05999        checkIsFunction(extract, true);
 06000      }
 6001
 06002      this.reporter = origReporter;
 06003    }
 6004
 6005    /// <summary>
 6006    /// Check that "stmt" is a valid statment for the body of an assert-by, forall,
 6007    /// or calc-hint statement. In particular, check that the local variables assigned in
 6008    /// the bodies of these statements are declared in the statements, not in some enclosing
 6009    /// context.
 6010    /// </summary>
 06011    public void CheckLocalityUpdates(Statement stmt, ISet<LocalVariable> localsAllowedInUpdates, string where) {
 6012      Contract.Requires(stmt != null);
 6013      Contract.Requires(localsAllowedInUpdates != null);
 6014      Contract.Requires(where != null);
 6015
 06016      if (stmt is AssertStmt || stmt is ForallStmt || stmt is CalcStmt || stmt is ModifyStmt) {
 6017        // don't recurse, since CheckHintRestrictions will be called on that assert-by separately
 06018        return;
 06019      } else if (stmt is AssignSuchThatStmt) {
 06020        var s = (AssignSuchThatStmt)stmt;
 06021        foreach (var lhs in s.Lhss) {
 06022          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06023        }
 06024      } else if (stmt is AssignStmt) {
 06025        var s = (AssignStmt)stmt;
 06026        CheckLocalityUpdatesLhs(s.Lhs, localsAllowedInUpdates, @where);
 06027      } else if (stmt is CallStmt) {
 06028        var s = (CallStmt)stmt;
 06029        foreach (var lhs in s.Lhs) {
 06030          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06031        }
 06032      } else if (stmt is VarDeclStmt) {
 06033        var s = (VarDeclStmt)stmt;
 06034        s.Locals.Iter(local => localsAllowedInUpdates.Add(local));
 06035      } else if (stmt is ModifyStmt) {
 6036        // no further complaints (note, ghost interests have already checked for 'modify' statements)
 06037      } else if (stmt is BlockStmt) {
 06038        localsAllowedInUpdates = new HashSet<LocalVariable>(localsAllowedInUpdates);
 6039        // use this new set for the recursive calls
 06040      }
 6041
 06042      foreach (var ss in stmt.SubStatements) {
 06043        CheckLocalityUpdates(ss, localsAllowedInUpdates, where);
 06044      }
 06045    }
 6046
 06047    void CheckLocalityUpdatesLhs(Expression lhs, ISet<LocalVariable> localsAllowedInUpdates, string @where) {
 6048      Contract.Requires(lhs != null);
 6049      Contract.Requires(localsAllowedInUpdates != null);
 6050      Contract.Requires(where != null);
 6051
 06052      lhs = lhs.Resolved;
 06053      if (lhs is IdentifierExpr idExpr && !localsAllowedInUpdates.Contains(idExpr.Var)) {
 06054        reporter.Error(MessageSource.Resolver, lhs.tok, "{0} is not allowed to update a variable it doesn't declare", wh
 06055      }
 06056    }
 6057
 6058    class LazyString_OnTypeEquals {
 6059      Type t0;
 6060      Type t1;
 6061      string s;
 06062      public LazyString_OnTypeEquals(Type t0, Type t1, string s) {
 6063        Contract.Requires(t0 != null);
 6064        Contract.Requires(t1 != null);
 6065        Contract.Requires(s != null);
 06066        this.t0 = t0;
 06067        this.t1 = t1;
 06068        this.s = s;
 06069      }
 06070      public override string ToString() {
 06071        return t0.Equals(t1) ? s : "";
 06072      }
 6073    }
 6074
 06075    void FindAllMembers(ClassDecl cl, string memberName, ISet<MemberDecl> foundSoFar) {
 6076      Contract.Requires(cl != null);
 6077      Contract.Requires(memberName != null);
 6078      Contract.Requires(foundSoFar != null);
 6079      MemberDecl member;
 06080      if (classMembers[cl].TryGetValue(memberName, out member)) {
 06081        foundSoFar.Add(member);
 06082      }
 06083      cl.ParentTraitHeads.ForEach(trait => FindAllMembers(trait, memberName, foundSoFar));
 06084    }
 6085
 6086    // TODO move
 8906087    public static UserDefinedType GetThisType(IToken tok, TopLevelDeclWithMembers cl) {
 6088      Contract.Requires(tok != null);
 6089      Contract.Requires(cl != null);
 6090      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6091
 17806092      if (cl is ClassDecl cls && cls.NonNullTypeDecl != null) {
 8906093        return UserDefinedType.FromTopLevelDecl(tok, cls.NonNullTypeDecl, cls.TypeArgs);
 06094      } else {
 06095        return UserDefinedType.FromTopLevelDecl(tok, cl, cl.TypeArgs);
 6096      }
 8906097    }
 6098
 6099    // TODO move
 06100    public static UserDefinedType GetReceiverType(IToken tok, MemberDecl member) {
 6101      Contract.Requires(tok != null);
 6102      Contract.Requires(member != null);
 6103      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6104
 06105      return GetThisType(tok, (TopLevelDeclWithMembers)member.EnclosingClass);
 06106    }
 6107
 06108    Label/*?*/ ResolveDominatingLabelInExpr(IToken tok, string/*?*/ labelName, string expressionDescription, ResolutionC
 6109      Contract.Requires(tok != null);
 6110      Contract.Requires(expressionDescription != null);
 6111      Contract.Requires(resolutionContext != null);
 6112
 06113      Label label = null;
 06114      if (!resolutionContext.IsTwoState) {
 06115        reporter.Error(MessageSource.Resolver, tok, $"{expressionDescription} expressions are not allowed in this contex
 06116      } else if (labelName != null) {
 06117        label = DominatingStatementLabels.Find(labelName);
 06118        if (label == null) {
 06119          reporter.Error(MessageSource.Resolver, tok, $"no label '{labelName}' in scope at this time");
 06120        }
 06121      }
 06122      return label;
 06123    }
 6124
 06125    private Expression VarDotFunction(IToken tok, string varname, string functionname) {
 06126      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), functionname, null), new 
 06127    }
 6128
 6129    // TODO search for occurrences of "new LetExpr" which could benefit from this helper
 06130    private LetExpr LetPatIn(IToken tok, CasePattern<BoundVar> lhs, Expression rhs, Expression body) {
 06131      return new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { rhs }, body, true);
 06132    }
 6133
 06134    private LetExpr LetVarIn(IToken tok, string name, Type tp, Expression rhs, Expression body) {
 06135      var lhs = new CasePattern<BoundVar>(tok, new BoundVar(tok, name, tp));
 06136      return LetPatIn(tok, lhs, rhs, body);
 06137    }
 6138
 6139    /// <summary>
 6140    ///  If expr.Lhs != null: Desugars "var x: T :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6141    ///  If expr.Lhs == null: Desugars "         :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6142    /// </summary>
 06143    public void ResolveLetOrFailExpr(LetOrFailExpr expr, ResolutionContext resolutionContext) {
 06144      var temp = FreshTempVarName("valueOrError", resolutionContext.CodeContext);
 06145      var tempType = new InferredTypeProxy();
 6146      // "var temp := E;"
 06147      expr.ResolvedExpression = LetVarIn(expr.tok, temp, tempType, expr.Rhs,
 06148        // "if temp.IsFailure()"
 06149        new ITEExpr(expr.tok, false, VarDotFunction(expr.tok, temp, "IsFailure"),
 06150          // "then temp.PropagateFailure()"
 06151          VarDotFunction(expr.tok, temp, "PropagateFailure"),
 06152          // "else"
 06153          expr.Lhs == null
 06154            // "F"
 06155            ? expr.Body
 06156            // "var x: T := temp.Extract(); F"
 06157            : LetPatIn(expr.tok, expr.Lhs, VarDotFunction(expr.tok, temp, "Extract"), expr.Body)));
 6158
 06159      ResolveExpression(expr.ResolvedExpression, resolutionContext);
 06160      expr.Type = expr.ResolvedExpression.Type;
 06161      bool expectExtract = (expr.Lhs != null);
 06162      EnsureSupportsErrorHandling(expr.tok, PartiallyResolveTypeForMemberSelection(expr.tok, tempType), expectExtract, f
 06163    }
 6164
 101706165    public static Type SelectAppropriateArrowTypeForFunction(Function function, Dictionary<TypeParameter, Type> subst, B
 101706166      return SelectAppropriateArrowType(function.tok,
 261806167        function.Formals.ConvertAll(formal => formal.Type.Subst(subst)),
 101706168        function.ResultType.Subst(subst),
 101706169        function.Reads.Count != 0, function.Req.Count != 0,
 101706170        builtIns);
 101706171    }
 6172
 149306173    public static Type SelectAppropriateArrowType(IToken tok, List<Type> typeArgs, Type resultType, bool hasReads, bool 
 6174      Contract.Requires(tok != null);
 6175      Contract.Requires(typeArgs != null);
 6176      Contract.Requires(resultType != null);
 149306177      var arity = typeArgs.Count;
 149306178      var typeArgsAndResult = Util.Snoc(typeArgs, resultType);
 149306179      if (hasReads) {
 6180        // any arrow
 06181        return new ArrowType(tok, builtIns.ArrowTypeDecls[arity], typeArgsAndResult);
 149306182      } else if (hasReq) {
 6183        // partial arrow
 06184        return new UserDefinedType(tok, ArrowType.PartialArrowTypeName(arity), builtIns.PartialArrowTypeDecls[arity], ty
 149306185      } else {
 6186        // total arrow
 149306187        return new UserDefinedType(tok, ArrowType.TotalArrowTypeName(arity), builtIns.TotalArrowTypeDecls[arity], typeAr
 6188      }
 149306189    }
 6190
 6191    /// <summary>
 6192    /// Adds appropriate type constraints that says "expr" evaluates to an integer or (if "allowBitVector" is true) a
 6193    /// a bitvector.  The "errFormat" string can contain a "{0}", referring to the name of the type of "expr".
 6194    /// </summary>
 12306195    void ConstrainToIntegerType(Expression expr, bool allowBitVector, string errFormat) {
 6196      Contract.Requires(expr != null);
 6197      Contract.Requires(errFormat != null);
 12306198      var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, errFormat, expr.Type);
 12306199      ConstrainToIntegerType(expr.tok, expr.Type, allowBitVector, err);
 12306200    }
 6201
 6202    /// <summary>
 6203    /// Resolves a NestedMatchExpr by
 6204    /// 1 - checking that all of its patterns are linear
 6205    /// 2 - desugaring it into a decision tree of MatchExpr and ITEEXpr (for constant matching)
 6206    /// 3 - resolving the generated (sub)expression.
 6207    /// </summary>
 06208    void ResolveNestedMatchExpr(NestedMatchExpr nestedMatchExpr, ResolutionContext resolutionContext) {
 6209      Contract.Requires(nestedMatchExpr != null);
 6210      Contract.Requires(resolutionContext != null);
 6211
 06212      nestedMatchExpr.Resolve(this, resolutionContext);
 06213    }
 6214
 6215    void ResolveCasePattern<VT>(CasePattern<VT> pat, Type sourceType, ResolutionContext resolutionContext)
 364506216      where VT : class, IVariable {
 6217      Contract.Requires(pat != null);
 6218      Contract.Requires(sourceType != null);
 6219      Contract.Requires(resolutionContext != null);
 6220
 364506221      DatatypeDecl dtd = null;
 364506222      UserDefinedType udt = null;
 398706223      if (sourceType.IsDatatype) {
 34206224        udt = (UserDefinedType)sourceType.NormalizeExpand();
 34206225        dtd = (DatatypeDecl)udt.ResolvedClass;
 34206226      }
 6227      // Find the constructor in the given datatype
 6228      // If what was parsed was just an identifier, we will interpret it as a datatype constructor, if possible
 364506229      DatatypeCtor ctor = null;
 398706230      if (dtd != null) {
 68406231        if (pat.Var == null || (pat.Var != null && pat.Var.Type is TypeProxy)) {
 34206232          if (dtd.ConstructorsByName.TryGetValue(pat.Id, out ctor)) {
 06233            if (pat.Arguments == null) {
 06234              if (ctor.Formals.Count != 0) {
 6235                // Leave this as a variable
 06236              } else {
 6237                // Convert to a constructor
 06238                pat.MakeAConstructor();
 06239                pat.Ctor = ctor;
 06240                pat.Var = default(VT);
 06241              }
 06242            } else {
 06243              pat.Ctor = ctor;
 06244              pat.Var = default(VT);
 06245            }
 06246          }
 34206247        }
 34206248      }
 6249
 729006250      if (pat.Var != null) {
 6251        // this is a simple resolution
 364506252        var v = pat.Var;
 364506253        if (resolutionContext.IsGhost) {
 06254          v.MakeGhost();
 06255        }
 364506256        ResolveType(v.Tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 6257        // Note, the following type constraint checks that the RHS type can be assigned to the new variable on the left.
 6258        // does not check that the entire RHS can be assigned to something of the type of the pattern on the left.  For 
 6259        // a type declared as "datatype Atom<T> = MakeAtom(T)", where T is a non-variant type argument.  Suppose the RHS
 6260        // and that the LHS is the pattern MakeAtom(x: int).  This is okay, despite the fact that Atom<nat> is not assig
 6261        // The reason is that the purpose of the pattern on the left is really just to provide a skeleton to introduce b
 364506262        EagerAddAssignableConstraint(v.Tok, v.Type, sourceType, "type of corresponding source/RHS ({1}) does not match t
 364506263        pat.AssembleExpr(null);
 364506264        return;
 6265      }
 06266      if (dtd == null) {
 6267        // look up the name of the pattern's constructor
 6268        Tuple<DatatypeCtor, bool> pair;
 06269        if (moduleInfo.Ctors.TryGetValue(pat.Id, out pair) && !pair.Item2) {
 06270          ctor = pair.Item1;
 06271          pat.Ctor = ctor;
 06272          dtd = ctor.EnclosingDatatype;
 06273          var typeArgs = new List<Type>();
 06274          foreach (var xt in dtd.TypeArgs) {
 06275            typeArgs.Add(new InferredTypeProxy());
 06276          }
 06277          udt = new UserDefinedType(pat.tok, dtd.Name, dtd, typeArgs);
 06278          ConstrainSubtypeRelation(udt, sourceType, pat.tok, "type of RHS ({0}) does not match type of bound variable '{
 06279        }
 06280      }
 06281      if (dtd == null && ctor == null) {
 06282        reporter.Error(MessageSource.Resolver, pat.tok, "to use a pattern, the type of the source/RHS expression must be
 06283      } else if (ctor == null) {
 06284        reporter.Error(MessageSource.Resolver, pat.tok, "constructor {0} does not exist in datatype {1}", pat.Id, dtd.Na
 06285      } else {
 06286        if (pat.Arguments == null) {
 06287          if (ctor.Formals.Count == 0) {
 6288            // The Id matches a constructor of the correct type and 0 arguments,
 6289            // so make it a nullary constructor, not a variable
 06290            pat.MakeAConstructor();
 06291          }
 06292        } else {
 06293          if (ctor.Formals.Count != pat.Arguments.Count) {
 06294            reporter.Error(MessageSource.Resolver, pat.tok, "pattern for constructor {0} has wrong number of formals (fo
 06295          }
 06296        }
 6297        // build the type-parameter substitution map for this use of the datatype
 06298        Contract.Assert(dtd.TypeArgs.Count == udt.TypeArgs.Count);  // follows from the type previously having been succ
 06299        var subst = TypeParameter.SubstitutionMap(dtd.TypeArgs, udt.TypeArgs);
 6300        // recursively call ResolveCasePattern on each of the arguments
 06301        var j = 0;
 06302        if (pat.Arguments != null) {
 06303          foreach (var arg in pat.Arguments) {
 06304            if (j < ctor.Formals.Count) {
 06305              var formal = ctor.Formals[j];
 06306              Type st = formal.Type.Subst(subst);
 06307              ResolveCasePattern(arg, st, resolutionContext.WithGhost(resolutionContext.IsGhost || formal.IsGhost));
 06308            }
 06309            j++;
 06310          }
 06311        }
 06312        if (j == ctor.Formals.Count) {
 06313          pat.AssembleExpr(udt.TypeArgs);
 06314        }
 06315      }
 364506316    }
 6317
 4456318    private List<DefaultValueExpression> allDefaultValueExpressions = new List<DefaultValueExpression>();
 6319
 6320    /// <summary>
 6321    /// This method is called at the tail end of Pass1 of the Resolver.
 6322    /// </summary>
 13356323    void FillInDefaultValueExpressions() {
 13356324      var visited = new Dictionary<DefaultValueExpression, WorkProgress>();
 40056325      foreach (var e in allDefaultValueExpressions) {
 06326        FillInDefaultValueExpression(e, visited);
 06327      }
 13356328      allDefaultValueExpressions.Clear();
 13356329    }
 6330
 6331    enum WorkProgress { BeingVisited, Done }
 6332
 06333    void FillInDefaultValueExpression(DefaultValueExpression expr, Dictionary<DefaultValueExpression, WorkProgress> visi
 6334      Contract.Requires(expr != null);
 6335      Contract.Requires(visited != null);
 6336      Contract.Ensures(expr.ResolvedExpression != null);
 6337
 06338      if (visited.TryGetValue(expr, out var p)) {
 06339        if (p == WorkProgress.Done) {
 06340          Contract.Assert(expr.ResolvedExpression != null);
 06341        } else {
 6342          // there is a cycle
 06343          reporter.Error(MessageSource.Resolver, expr, "default-valued expressions are cyclicly dependent; this is not a
 6344          // nevertheless, to avoid any issues in the resolver, fill in the .ResolvedExpression field with something
 06345          expr.ResolvedExpression = Expression.CreateBoolLiteral(expr.tok, false);
 06346        }
 06347        return;
 6348      }
 06349      Contract.Assert(expr.ResolvedExpression == null);
 6350
 06351      visited.Add(expr, WorkProgress.BeingVisited);
 06352      var s = new DefaultValueSubstituter(this, visited, expr.Receiver, expr.SubstMap, expr.TypeMap);
 06353      expr.ResolvedExpression = s.Substitute(expr.Formal.DefaultValue);
 06354      visited[expr] = WorkProgress.Done;
 06355    }
 6356
 6357    class DefaultValueSubstituter : Substituter {
 6358      private readonly Resolver resolver;
 6359      private readonly Dictionary<DefaultValueExpression, WorkProgress> visited;
 6360      public DefaultValueSubstituter(Resolver resolver, Dictionary<DefaultValueExpression, WorkProgress> visited,
 6361        Expression /*?*/ receiverReplacement, Dictionary<IVariable, Expression> substMap, Dictionary<TypeParameter, Type
 06362        : base(receiverReplacement, substMap, typeMap) {
 6363        Contract.Requires(resolver != null);
 6364        Contract.Requires(visited != null);
 06365        this.resolver = resolver;
 06366        this.visited = visited;
 06367      }
 6368
 06369      public override Expression Substitute(Expression expr) {
 06370        if (expr is DefaultValueExpression dve) {
 06371          resolver.FillInDefaultValueExpression(dve, visited);
 06372          Contract.Assert(dve.ResolvedExpression != null); // postcondition of FillInDefaultValueExpression
 06373        }
 06374        return base.Substitute(expr);
 06375      }
 6376    }
 6377
 6378    public Dictionary<TypeParameter, Type> BuildTypeArgumentSubstitute(Dictionary<TypeParameter, Type> typeArgumentSubst
 387406379      Type/*?*/ receiverTypeBound = null) {
 6380      Contract.Requires(typeArgumentSubstitutions != null);
 6381
 387406382      var subst = new Dictionary<TypeParameter, Type>();
 2180406383      foreach (var entry in typeArgumentSubstitutions) {
 339406384        subst.Add(entry.Key, entry.Value);
 339406385      }
 6386
 387406387      if (SelfTypeSubstitution != null) {
 06388        foreach (var entry in SelfTypeSubstitution) {
 06389          subst.Add(entry.Key, entry.Value);
 06390        }
 06391      }
 6392
 695406393      if (receiverTypeBound != null) {
 308006394        subst = AddParentTypeParameterSubstitutions(subst, receiverTypeBound);
 308006395      }
 6396
 387406397      return subst;
 387406398    }
 6399
 308006400    public static Dictionary<TypeParameter, Type> AddParentTypeParameterSubstitutions(Dictionary<TypeParameter, Type> su
 6401      TopLevelDeclWithMembers cl;
 308006402      var udt = receiverType?.AsNonNullRefType;
 308006403      if (udt != null) {
 06404        cl = (TopLevelDeclWithMembers)((NonNullTypeDecl)udt.ResolvedClass).ViewAsClass;
 308006405      } else {
 308006406        udt = receiverType.NormalizeExpand() as UserDefinedType;
 308006407        cl = udt?.ResolvedClass as TopLevelDeclWithMembers;
 308006408      }
 616006409      if (cl != null) {
 924006410        foreach (var entry in cl.ParentFormalTypeParametersToActuals) {
 06411          var v = entry.Value.Subst(subst);
 06412          subst.Add(entry.Key, v);
 06413        }
 308006414      }
 6415
 308006416      return subst;
 308006417    }
 6418
 1081896419    public static string GhostPrefix(bool isGhost) {
 1081896420      return isGhost ? "ghost " : "";
 1081896421    }
 6422
 06423    private static ModuleSignature GetSignatureExt(ModuleSignature sig, bool useCompileSignatures) {
 6424      Contract.Requires(sig != null);
 6425      Contract.Ensures(Contract.Result<ModuleSignature>() != null);
 06426      if (useCompileSignatures) {
 06427        while (sig.CompileSignature != null) {
 06428          sig = sig.CompileSignature;
 06429        }
 06430      }
 06431      return sig;
 06432    }
 6433
 06434    private ModuleSignature GetSignature(ModuleSignature sig) {
 06435      return GetSignatureExt(sig, useCompileSignatures);
 06436    }
 6437
 4456438    public static Expression GetImpliedTypeConstraint(IVariable bv, Type ty) {
 4456439      return GetImpliedTypeConstraint(Expression.CreateIdentExpr(bv), ty);
 4456440    }
 6441
 26706442    public static Expression GetImpliedTypeConstraint(Expression e, Type ty) {
 6443      Contract.Requires(e != null);
 6444      Contract.Requires(ty != null);
 26706445      ty = ty.NormalizeExpandKeepConstraints();
 26706446      var udt = ty as UserDefinedType;
 40056447      if (udt != null) {
 13356448        if (udt.ResolvedClass is NewtypeDecl) {
 06449          var dd = (NewtypeDecl)udt.ResolvedClass;
 06450          var c = GetImpliedTypeConstraint(e, dd.BaseType);
 06451          if (dd.Var != null) {
 06452            Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 06453            substMap.Add(dd.Var, e);
 06454            Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 06455            c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 06456          }
 06457          return c;
 26706458        } else if (udt.ResolvedClass is SubsetTypeDecl) {
 13356459          var dd = (SubsetTypeDecl)udt.ResolvedClass;
 13356460          var c = GetImpliedTypeConstraint(e, dd.RhsWithArgument(udt.TypeArgs));
 13356461          Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 13356462          substMap.Add(dd.Var, e);
 13356463          Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 13356464          c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 13356465          return c;
 6466        }
 06467      }
 13356468      return Expression.CreateBoolLiteral(e.tok, true);
 26706469    }
 6470
 6471    /// <summary>
 6472    /// Returns the set of free variables in "expr".
 6473    /// Requires "expr" to be successfully resolved.
 6474    /// Ensures that the set returned has no aliases.
 6475    /// </summary>
 06476    static ISet<IVariable> FreeVariables(Expression expr) {
 6477      Contract.Requires(expr != null);
 6478      Contract.Ensures(expr.Type != null);
 6479
 06480      if (expr is IdentifierExpr) {
 06481        var e = (IdentifierExpr)expr;
 06482        return new HashSet<IVariable>() { e.Var };
 6483
 06484      } else if (expr is QuantifierExpr) {
 06485        var e = (QuantifierExpr)expr;
 06486        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 6487
 06488        var s = FreeVariables(e.LogicalBody());
 06489        foreach (var bv in e.BoundVars) {
 06490          s.Remove(bv);
 06491        }
 06492        return s;
 06493      } else if (expr is NestedMatchExpr) {
 06494        var e = (NestedMatchExpr)expr;
 06495        var s = FreeVariables(e.Source);
 06496        foreach (NestedMatchCaseExpr mc in e.Cases) {
 06497          var t = FreeVariables(mc.Body);
 06498          foreach (var bv in mc.Pat.Children.OfType<IdPattern>()) {
 06499            if (bv.BoundVar != null) {
 06500              t.Remove(bv.BoundVar);
 06501            }
 06502          }
 06503          s.UnionWith(t);
 06504        }
 06505        return s;
 06506      } else if (expr is MatchExpr) {
 06507        var e = (MatchExpr)expr;
 06508        var s = FreeVariables(e.Source);
 06509        foreach (MatchCaseExpr mc in e.Cases) {
 06510          var t = FreeVariables(mc.Body);
 06511          foreach (var bv in mc.Arguments) {
 06512            t.Remove(bv);
 06513          }
 06514          s.UnionWith(t);
 06515        }
 06516        return s;
 6517
 06518      } else if (expr is LambdaExpr) {
 06519        var e = (LambdaExpr)expr;
 06520        var s = FreeVariables(e.Term);
 06521        if (e.Range != null) {
 06522          s.UnionWith(FreeVariables(e.Range));
 06523        }
 06524        foreach (var fe in e.Reads) {
 06525          s.UnionWith(FreeVariables(fe.E));
 06526        }
 06527        foreach (var bv in e.BoundVars) {
 06528          s.Remove(bv);
 06529        }
 06530        return s;
 6531
 06532      } else {
 06533        ISet<IVariable> s = null;
 06534        foreach (var e in expr.SubExpressions) {
 06535          var t = FreeVariables(e);
 06536          if (s == null) {
 06537            s = t;
 06538          } else {
 06539            s.UnionWith(t);
 06540          }
 06541        }
 06542        return s == null ? new HashSet<IVariable>() : s;
 6543      }
 06544    }
 6545
 6546    /// <summary>
 6547    /// An error message for the type constraint for between a sequence select expression's actual and expected types.
 6548    /// If resolution successfully determines the sequences' element types, then this derived class mentions those
 6549    /// element types as clarifying context to the user.
 6550    /// </summary>
 6551    private class SeqSelectOneErrorMsg : TypeConstraint.ErrorMsgWithToken {
 4456552      private static readonly string BASE_MESSAGE_FORMAT = "sequence has type {0} which is incompatible with expected ty
 4456553      private static readonly string ELEMENT_DETAIL_MESSAGE_FORMAT = " (element type {0} is incompatible with {1})";
 6554
 6555      private readonly Type exprSeqType;
 6556      private readonly Type expectedSeqType;
 6557
 6558      public override string Msg {
 06559        get {
 6560          // Resolution might resolve exprSeqType/expectedSeqType to not be sequences at all.
 6561          // In that case, it isn't possible to get the corresponding element types.
 06562          var rawExprElementType = exprSeqType.AsSeqType?.Arg;
 06563          var rawExpectedElementType = expectedSeqType.AsSeqType?.Arg;
 06564          if (rawExprElementType == null || rawExpectedElementType == null) {
 06565            return base.Msg;
 6566          }
 6567
 06568          var elementTypes = RemoveAmbiguity(new object[] { rawExprElementType, rawExpectedElementType });
 06569          Contract.Assert(elementTypes.Length == 2);
 06570          var exprElementType = elementTypes[0].ToString();
 06571          var expectedElementType = elementTypes[1].ToString();
 6572
 06573          string detail = string.Format(ELEMENT_DETAIL_MESSAGE_FORMAT, exprElementType, expectedElementType);
 06574          return base.Msg + detail;
 06575        }
 6576      }
 6577
 6578      public SeqSelectOneErrorMsg(IToken tok, Type exprSeqType, Type expectedSeqType)
 26406579        : base(tok, BASE_MESSAGE_FORMAT, exprSeqType, expectedSeqType) {
 6580        Contract.Requires(exprSeqType != null);
 6581        Contract.Requires(expectedSeqType != null);
 13206582        this.exprSeqType = exprSeqType;
 13206583        this.expectedSeqType = expectedSeqType;
 13206584      }
 6585    }
 6586
 6587    /// <summary>
 6588    /// Note: this method is allowed to be called even if "type" does not make sense for "op", as might be the case if
 6589    /// resolution of the binary expression failed.  If so, an arbitrary resolved opcode is returned.
 6590    /// Usually, the type of the right-hand operand is used to determine the resolved operator (hence, the shorter
 6591    /// name "operandType" instead of, say, "rightOperandType").
 6592    /// </summary>
 676106593    public static BinaryExpr.ResolvedOpcode ResolveOp(BinaryExpr.Opcode op, Type leftOperandType, Type operandType) {
 6594      Contract.Requires(leftOperandType != null);
 6595      Contract.Requires(operandType != null);
 676106596      leftOperandType = leftOperandType.NormalizeExpand();
 676106597      operandType = operandType.NormalizeExpand();
 676106598      switch (op) {
 3406599        case BinaryExpr.Opcode.Iff: return BinaryExpr.ResolvedOpcode.Iff;
 4106600        case BinaryExpr.Opcode.Imp: return BinaryExpr.ResolvedOpcode.Imp;
 4606601        case BinaryExpr.Opcode.Exp: return BinaryExpr.ResolvedOpcode.Imp;
 151806602        case BinaryExpr.Opcode.And: return BinaryExpr.ResolvedOpcode.And;
 2006603        case BinaryExpr.Opcode.Or: return BinaryExpr.ResolvedOpcode.Or;
 6604        case BinaryExpr.Opcode.Eq:
 21906605          if (operandType is SetType) {
 2806606            return BinaryExpr.ResolvedOpcode.SetEq;
 19506607          } else if (operandType is MultiSetType) {
 3206608            return BinaryExpr.ResolvedOpcode.MultiSetEq;
 13106609          } else if (operandType is SeqType) {
 06610            return BinaryExpr.ResolvedOpcode.SeqEq;
 13106611          } else if (operandType is MapType) {
 06612            return BinaryExpr.ResolvedOpcode.MapEq;
 13106613          } else {
 13106614            return BinaryExpr.ResolvedOpcode.EqCommon;
 6615          }
 6616        case BinaryExpr.Opcode.Neq:
 8906617          if (operandType is SetType) {
 06618            return BinaryExpr.ResolvedOpcode.SetNeq;
 8906619          } else if (operandType is MultiSetType) {
 06620            return BinaryExpr.ResolvedOpcode.MultiSetNeq;
 8906621          } else if (operandType is SeqType) {
 06622            return BinaryExpr.ResolvedOpcode.SeqNeq;
 8906623          } else if (operandType is MapType) {
 06624            return BinaryExpr.ResolvedOpcode.MapNeq;
 8906625          } else {
 8906626            return BinaryExpr.ResolvedOpcode.NeqCommon;
 6627          }
 6628        case BinaryExpr.Opcode.Disjoint:
 15206629          if (operandType is MultiSetType) {
 3706630            return BinaryExpr.ResolvedOpcode.MultiSetDisjoint;
 7806631          } else {
 7806632            return BinaryExpr.ResolvedOpcode.Disjoint;
 6633          }
 6634        case BinaryExpr.Opcode.Lt:
 34406635          if (operandType.IsIndDatatype) {
 06636            return BinaryExpr.ResolvedOpcode.RankLt;
 35406637          } else if (operandType is SetType) {
 1006638            return BinaryExpr.ResolvedOpcode.ProperSubset;
 34306639          } else if (operandType is MultiSetType) {
 906640            return BinaryExpr.ResolvedOpcode.ProperMultiSubset;
 32506641          } else if (operandType is SeqType) {
 06642            return BinaryExpr.ResolvedOpcode.ProperPrefix;
 34306643          } else if (operandType is CharType) {
 1806644            return BinaryExpr.ResolvedOpcode.LtChar;
 30706645          } else {
 30706646            return BinaryExpr.ResolvedOpcode.Lt;
 6647          }
 6648        case BinaryExpr.Opcode.Le:
 202306649          if (operandType is SetType) {
 1106650            return BinaryExpr.ResolvedOpcode.Subset;
 201106651          } else if (operandType is MultiSetType) {
 1006652            return BinaryExpr.ResolvedOpcode.MultiSubset;
 199106653          } else if (operandType is SeqType) {
 06654            return BinaryExpr.ResolvedOpcode.Prefix;
 201606655          } else if (operandType is CharType) {
 2506656            return BinaryExpr.ResolvedOpcode.LeChar;
 196606657          } else {
 196606658            return BinaryExpr.ResolvedOpcode.Le;
 6659          }
 6660        case BinaryExpr.Opcode.LeftShift:
 06661          return BinaryExpr.ResolvedOpcode.LeftShift;
 6662        case BinaryExpr.Opcode.RightShift:
 06663          return BinaryExpr.ResolvedOpcode.RightShift;
 6664        case BinaryExpr.Opcode.Add:
 175006665          if (operandType is SetType) {
 9806666            return BinaryExpr.ResolvedOpcode.Union;
 162006667          } else if (operandType is MultiSetType) {
 6606668            return BinaryExpr.ResolvedOpcode.MultiSetUnion;
 148806669          } else if (operandType is MapType) {
 06670            return BinaryExpr.ResolvedOpcode.MapMerge;
 153606671          } else if (operandType is SeqType) {
 4806672            return BinaryExpr.ResolvedOpcode.Concat;
 144006673          } else {
 144006674            return BinaryExpr.ResolvedOpcode.Add;
 6675          }
 6676        case BinaryExpr.Opcode.Sub:
 15006677          if (leftOperandType is MapType) {
 06678            return BinaryExpr.ResolvedOpcode.MapSubtraction;
 23106679          } else if (operandType is SetType) {
 8106680            return BinaryExpr.ResolvedOpcode.SetDifference;
 12706681          } else if (operandType is MultiSetType) {
 5806682            return BinaryExpr.ResolvedOpcode.MultiSetDifference;
 1106683          } else {
 1106684            return BinaryExpr.ResolvedOpcode.Sub;
 6685          }
 6686        case BinaryExpr.Opcode.Mul:
 16306687          if (operandType is SetType) {
 7806688            return BinaryExpr.ResolvedOpcode.Intersection;
 706689          } else if (operandType is MultiSetType) {
 06690            return BinaryExpr.ResolvedOpcode.MultiSetIntersection;
 706691          } else {
 706692            return BinaryExpr.ResolvedOpcode.Mul;
 6693          }
 6694        case BinaryExpr.Opcode.Gt:
 7206695          if (operandType.IsDatatype) {
 06696            return BinaryExpr.ResolvedOpcode.RankGt;
 8306697          } else if (operandType is SetType) {
 1106698            return BinaryExpr.ResolvedOpcode.ProperSuperset;
 7506699          } else if (operandType is MultiSetType) {
 1406700            return BinaryExpr.ResolvedOpcode.ProperMultiSuperset;
 5806701          } else if (operandType is CharType) {
 1106702            return BinaryExpr.ResolvedOpcode.GtChar;
 3606703          } else {
 3606704            return BinaryExpr.ResolvedOpcode.Gt;
 6705          }
 6706        case BinaryExpr.Opcode.Ge:
 7406707          if (operandType is SetType) {
 1506708            return BinaryExpr.ResolvedOpcode.Superset;
 5906709          } else if (operandType is MultiSetType) {
 1506710            return BinaryExpr.ResolvedOpcode.MultiSuperset;
 4406711          } else if (operandType is CharType) {
 1506712            return BinaryExpr.ResolvedOpcode.GeChar;
 1406713          } else {
 1406714            return BinaryExpr.ResolvedOpcode.Ge;
 6715          }
 6716        case BinaryExpr.Opcode.In:
 10106717          if (operandType is SetType) {
 2606718            return BinaryExpr.ResolvedOpcode.InSet;
 7306719          } else if (operandType is MultiSetType) {
 2406720            return BinaryExpr.ResolvedOpcode.InMultiSet;
 2506721          } else if (operandType is MapType) {
 06722            return BinaryExpr.ResolvedOpcode.InMap;
 2506723          } else {
 2506724            return BinaryExpr.ResolvedOpcode.InSeq;
 6725          }
 6726        case BinaryExpr.Opcode.NotIn:
 10706727          if (operandType is SetType) {
 2706728            return BinaryExpr.ResolvedOpcode.NotInSet;
 8006729          } else if (operandType is MultiSetType) {
 2706730            return BinaryExpr.ResolvedOpcode.NotInMultiSet;
 2606731          } else if (operandType is MapType) {
 06732            return BinaryExpr.ResolvedOpcode.NotInMap;
 2606733          } else {
 2606734            return BinaryExpr.ResolvedOpcode.NotInSeq;
 6735          }
 8906736        case BinaryExpr.Opcode.Div: return BinaryExpr.ResolvedOpcode.Div;
 8906737        case BinaryExpr.Opcode.Mod: return BinaryExpr.ResolvedOpcode.Mod;
 06738        case BinaryExpr.Opcode.BitwiseAnd: return BinaryExpr.ResolvedOpcode.BitwiseAnd;
 06739        case BinaryExpr.Opcode.BitwiseOr: return BinaryExpr.ResolvedOpcode.BitwiseOr;
 06740        case BinaryExpr.Opcode.BitwiseXor: return BinaryExpr.ResolvedOpcode.BitwiseXor;
 6741        default:
 06742          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 6743      }
 676106744    }
 6745
 6746    /// <summary>
 6747    /// This method adds to "friendlyCalls" all
 6748    ///     inductive calls                                     if !co
 6749    ///     greatest predicate calls and codatatype equalities  if co
 6750    /// that occur in positive positions and not under
 6751    ///     universal quantification                            if !co
 6752    ///     existential quantification.                         if co
 6753    /// If "expr" is the
 6754    ///     precondition of a least lemma                       if !co
 6755    ///     postcondition of a greatest lemma,                  if co
 6756    /// then the "friendlyCalls" are the subexpressions that need to be replaced in order
 6757    /// to create the
 6758    ///     precondition                                        if !co
 6759    ///     postcondition                                       if co
 6760    /// of the corresponding prefix lemma.
 6761    /// </summary>
 06762    void CollectFriendlyCallsInExtremeLemmaSpecification(Expression expr, bool position, ISet<Expression> friendlyCalls,
 6763      Contract.Requires(expr != null);
 6764      Contract.Requires(friendlyCalls != null);
 06765      var visitor = new CollectFriendlyCallsInSpec_Visitor(this, friendlyCalls, co, context);
 06766      visitor.Visit(expr, position ? CallingPosition.Positive : CallingPosition.Negative);
 06767    }
 6768
 6769    class CollectFriendlyCallsInSpec_Visitor : FindFriendlyCalls_Visitor {
 6770      readonly ISet<Expression> friendlyCalls;
 6771      readonly ExtremeLemma Context;
 6772      public CollectFriendlyCallsInSpec_Visitor(Resolver resolver, ISet<Expression> friendlyCalls, bool co, ExtremeLemma
 06773        : base(resolver, co, context.KNat) {
 6774        Contract.Requires(resolver != null);
 6775        Contract.Requires(friendlyCalls != null);
 6776        Contract.Requires(context != null);
 06777        this.friendlyCalls = friendlyCalls;
 06778        this.Context = context;
 06779      }
 06780      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 06781        if (cp == CallingPosition.Neither) {
 6782          // no friendly calls in "expr"
 06783          return false;  // don't recurse into subexpressions
 6784        }
 06785        if (expr is FunctionCallExpr) {
 06786          if (cp == CallingPosition.Positive) {
 06787            var fexp = (FunctionCallExpr)expr;
 06788            if (IsCoContext ? fexp.Function is GreatestPredicate : fexp.Function is LeastPredicate) {
 06789              if (Context.KNat != ((ExtremePredicate)fexp.Function).KNat) {
 06790                resolver.KNatMismatchError(expr.tok, Context.Name, Context.TypeOfK, ((ExtremePredicate)fexp.Function).Ty
 06791              } else {
 06792                friendlyCalls.Add(fexp);
 06793              }
 06794            }
 06795          }
 06796          return false;  // don't explore subexpressions any further
 06797        } else if (expr is BinaryExpr && IsCoContext) {
 06798          var bin = (BinaryExpr)expr;
 06799          if (cp == CallingPosition.Positive && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon && bin.E0.Type.IsCo
 06800            friendlyCalls.Add(bin);
 06801            return false;  // don't explore subexpressions any further
 06802          } else if (cp == CallingPosition.Negative && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon && bin.E0.T
 06803            friendlyCalls.Add(bin);
 06804            return false;  // don't explore subexpressions any further
 6805          }
 06806        }
 06807        return base.VisitOneExpr(expr, ref cp);
 06808      }
 6809    }
 6810  }
 6811
 6812  abstract class ResolverTopDownVisitor<T> : TopDownVisitor<T> {
 6813    protected Resolver resolver;
 6814    public ResolverTopDownVisitor(Resolver resolver) {
 6815      Contract.Requires(resolver != null);
 6816      this.resolver = resolver;
 6817    }
 6818  }
 6819
 6820  class CoCallResolution {
 6821    readonly Function currentFunction;
 6822    readonly bool dealsWithCodatatypes;
 6823    public bool HasIntraClusterCallsInDestructiveContexts = false;
 6824    public readonly List<CoCallInfo> FinalCandidates = new List<CoCallInfo>();
 6825
 6826    public CoCallResolution(Function currentFunction, bool dealsWithCodatatypes) {
 6827      Contract.Requires(currentFunction != null);
 6828      this.currentFunction = currentFunction;
 6829      this.dealsWithCodatatypes = dealsWithCodatatypes;
 6830    }
 6831
 6832    /// <summary>
 6833    /// Determines which calls in "expr" can be considered to be co-calls, which co-constructor
 6834    /// invocations host such co-calls, and which destructor operations are not allowed.
 6835    /// Also records whether or not there are any intra-cluster calls in a destructive context.
 6836    /// Assumes "expr" to have been successfully resolved.
 6837    /// </summary>
 6838    public void CheckCoCalls(Expression expr) {
 6839      Contract.Requires(expr != null);
 6840      CheckCoCalls(expr, 0, null, FinalCandidates);
 6841    }
 6842
 6843    public struct CoCallInfo {
 6844      public readonly FunctionCallExpr CandidateCall;
 6845      public readonly DatatypeValue EnclosingCoConstructor;
 6846      public CoCallInfo(FunctionCallExpr candidateCall, DatatypeValue enclosingCoConstructor) {
 6847        Contract.Requires(candidateCall != null);
 6848        Contract.Requires(enclosingCoConstructor != null);
 6849        CandidateCall = candidateCall;
 6850        EnclosingCoConstructor = enclosingCoConstructor;
 6851      }
 6852    }
 6853
 6854    /// <summary>
 6855    /// Recursively goes through the entire "expr".  Every call within the same recursive cluster is a potential
 6856    /// co-call.  If the call is determined not to be a co-recursive call, then its .CoCall field is filled in;
 6857    /// if the situation deals with co-datatypes, then one of the NoBecause... values is chosen (rather
 6858    /// than just No), so that any error message that may later be produced when trying to prove termination of the
 6859    /// recursive call can include a note pointing out that the call was not selected to be a co-call.
 6860    /// If the call looks like it is guarded, then it is added to the list "coCandicates", so that a later analysis
 6861    /// can either set all of those .CoCall fields to Yes or to NoBecauseRecursiveCallsInDestructiveContext, depending
 6862    /// on other intra-cluster calls.
 6863    /// The "destructionLevel" indicates how many pending co-destructors the context has.  It may be infinity (int.MaxVa
 6864    /// if the enclosing context has no easy way of controlling the uses of "expr" (for example, if the enclosing contex
 6865    /// passes "expr" to a function or binds "expr" to a variable).  It is never negative -- excess co-constructors are
 6866    /// not considered an asset, and any immediately enclosing co-constructor is passed in as a non-null "coContext" any
 6867    /// "coContext" is non-null if the immediate context is a co-constructor.
 6868    /// </summary>
 6869    void CheckCoCalls(Expression expr, int destructionLevel, DatatypeValue coContext, List<CoCallInfo> coCandidates, Fun
 6870      Contract.Requires(expr != null);
 6871
 6872      Contract.Requires(0 <= destructionLevel);
 6873      Contract.Requires(coCandidates != null);
 6874      expr = expr.Resolved;
 6875      if (expr is DatatypeValue) {
 6876        var e = (DatatypeValue)expr;
 6877        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 6878          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel == 0 ? 0 : destructionLevel - 1;
 6879          foreach (var arg in e.Arguments) {
 6880            CheckCoCalls(arg, dl, e, coCandidates);
 6881          }
 6882          return;
 6883        }
 6884      } else if (expr is MemberSelectExpr) {
 6885        var e = (MemberSelectExpr)expr;
 6886        if (e.Member.EnclosingClass is CoDatatypeDecl) {
 6887          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel + 1;
 6888          CheckCoCalls(e.Obj, dl, coContext, coCandidates);
 6889          return;
 6890        }
 6891      } else if (expr is BinaryExpr) {
 6892        var e = (BinaryExpr)expr;
 6893        if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon || e.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon) {
 6894          // Equality and disequality (for any type that may contain a co-datatype) are as destructive as can be--in ess
 6895          // they destruct the values indefinitely--so don't allow any co-recursive calls in the operands.
 6896          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6897          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6898          return;
 6899        }
 6900      } else if (expr is TernaryExpr) {
 6901        var e = (TernaryExpr)expr;
 6902        if (e.Op == TernaryExpr.Opcode.PrefixEqOp || e.Op == TernaryExpr.Opcode.PrefixNeqOp) {
 6903          // Prefix equality and disequality (for any type that may contain a co-datatype) are destructive.
 6904          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6905          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6906          CheckCoCalls(e.E2, int.MaxValue, null, coCandidates);
 6907          return;
 6908        }
 6909      } else if (expr is NestedMatchExpr) {
 6910        var e = (NestedMatchExpr)expr;
 6911        foreach (var child in e.SubExpressions) {
 6912          CheckCoCalls(child, destructionLevel, coContext, coCandidates);
 6913        }
 6914      } else if (expr is MatchExpr) {
 6915        var e = (MatchExpr)expr;
 6916        CheckCoCalls(e.Source, int.MaxValue, null, coCandidates);
 6917        foreach (var kase in e.Cases) {
 6918          CheckCoCalls(kase.Body, destructionLevel, coContext, coCandidates);
 6919        }
 6920        return;
 6921      } else if (expr is ITEExpr) {
 6922        var e = (ITEExpr)expr;
 6923        CheckCoCalls(e.Test, int.MaxValue, null, coCandidates);
 6924        CheckCoCalls(e.Thn, destructionLevel, coContext, coCandidates);
 6925        CheckCoCalls(e.Els, destructionLevel, coContext, coCandidates);
 6926        return;
 6927      } else if (expr is FunctionCallExpr) {
 6928        var e = (FunctionCallExpr)expr;
 6929        // First, consider the arguments of the call, making sure that they do not include calls within the recursive cl
 6930        // unless the callee is abstemious.
 6931        var abstemious = true;
 6932        if (!Attributes.ContainsBool(e.Function.Attributes, "abstemious", ref abstemious)) {
 6933          abstemious = false;
 6934        }
 6935        Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 6936        for (var i = 0; i < e.Args.Count; i++) {
 6937          var arg = e.Args[i];
 6938          if (!e.Function.Formals[i].Type.IsCoDatatype) {
 6939            CheckCoCalls(arg, int.MaxValue, null, coCandidates);
 6940          } else if (abstemious) {
 6941            CheckCoCalls(arg, 0, coContext, coCandidates);
 6942          } else {
 6943            // don't you wish the callee were abstemious
 6944            CheckCoCalls(arg, int.MaxValue, null, coCandidates, e.Function);
 6945          }
 6946        }
 6947        // Second, investigate the possibility that this call itself may be a candidate co-call
 6948        if (e.Name != "requires" && ModuleDefinition.InSameSCC(currentFunction, e.Function)) {
 6949          // This call goes to another function in the same recursive cluster
 6950          if (destructionLevel != 0 && GuaranteedCoCtors(e.Function) <= destructionLevel) {
 6951            // a potentially destructive context
 6952            HasIntraClusterCallsInDestructiveContexts = true;  // this says we found an intra-cluster call unsuitable fo
 6953            if (!dealsWithCodatatypes) {
 6954              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6955            } else {
 6956              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsAreNotAllowedInThisContext;
 6957              if (functionYouMayWishWereAbstemious != null) {
 6958                e.CoCallHint = string.Format("perhaps try declaring function '{0}' with '{{:abstemious}}'", functionYouM
 6959              }
 6960            }
 6961          } else if (coContext == null) {
 6962            // no immediately enclosing co-constructor
 6963            if (!dealsWithCodatatypes) {
 6964              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6965            } else {
 6966              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseIsNotGuarded;
 6967            }
 6968          } else if (e.Function.Reads.Count != 0) {
 6969            // this call is disqualified from being a co-call, because of side effects
 6970            if (!dealsWithCodatatypes) {
 6971              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6972            } else {
 6973              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasSideEffects;
 6974            }
 6975          } else if (e.Function.Ens.Count != 0) {
 6976            // this call is disqualified from being a co-call, because it has a postcondition
 6977            // (a postcondition could be allowed, as long as it does not get to be used with
 6978            // co-recursive calls, because that could be unsound; for example, consider
 6979            // "ensures false")
 6980            if (!dealsWithCodatatypes) {
 6981              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6982            } else {
 6983              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasPostcondition;
 6984            }
 6985          } else {
 6986            // e.CoCall is not filled in here, but will be filled in when the list of candidates are processed
 6987            coCandidates.Add(new CoCallInfo(e, coContext));
 6988          }
 6989        }
 6990        return;
 6991      } else if (expr is LambdaExpr) {
 6992        var e = (LambdaExpr)expr;
 6993        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 6994        if (e.Range != null) {
 6995          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 6996        }
 6997        foreach (var read in e.Reads) {
 6998          CheckCoCalls(read.E, int.MaxValue, null, coCandidates);
 6999        }
 7000        return;
 7001      } else if (expr is MapComprehension) {
 7002        var e = (MapComprehension)expr;
 7003        foreach (var ee in Attributes.SubExpressions(e.Attributes)) {
 7004          CheckCoCalls(ee, int.MaxValue, null, coCandidates);
 7005        }
 7006        if (e.Range != null) {
 7007          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 7008        }
 7009        // allow co-calls in the term
 7010        if (e.TermLeft != null) {
 7011          CheckCoCalls(e.TermLeft, destructionLevel, coContext, coCandidates);
 7012        }
 7013        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 7014        return;
 7015      } else if (expr is OldExpr) {
 7016        var e = (OldExpr)expr;
 7017        // here, "coContext" is passed along (the use of "old" says this must be ghost code, so the compiler does not ne
 7018        CheckCoCalls(e.E, destructionLevel, coContext, coCandidates);
 7019        return;
 7020      } else if (expr is LetExpr) {
 7021        var e = (LetExpr)expr;
 7022        foreach (var rhs in e.RHSs) {
 7023          CheckCoCalls(rhs, int.MaxValue, null, coCandidates);
 7024        }
 7025        CheckCoCalls(e.Body, destructionLevel, coContext, coCandidates);
 7026        return;
 7027      } else if (expr is ApplyExpr) {
 7028        var e = (ApplyExpr)expr;
 7029        CheckCoCalls(e.Function, int.MaxValue, null, coCandidates);
 7030        foreach (var ee in e.Args) {
 7031          CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7032        }
 7033        return;
 7034      }
 7035
 7036      // Default handling:
 7037      foreach (var ee in expr.SubExpressions) {
 7038        CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7039      }
 7040    }
 7041
 7042    public static int GuaranteedCoCtors(Function function) {
 7043      Contract.Requires(function != null);
 7044      return function.Body != null ? GuaranteedCoCtorsAux(function.Body) : 0;
 7045    }
 7046
 7047    private static int GuaranteedCoCtorsAux(Expression expr) {
 7048      Contract.Requires(expr != null);
 7049      expr = expr.Resolved;
 7050      if (expr is DatatypeValue) {
 7051        var e = (DatatypeValue)expr;
 7052        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 7053          var minOfArgs = int.MaxValue;  // int.MaxValue means: not yet encountered a formal whose type is a co-datatype
 7054          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 7055          for (var i = 0; i < e.Arguments.Count; i++) {
 7056            if (e.Ctor.Formals[i].Type.IsCoDatatype) {
 7057              var n = GuaranteedCoCtorsAux(e.Arguments[i]);
 7058              minOfArgs = Math.Min(minOfArgs, n);
 7059            }
 7060          }
 7061          return minOfArgs == int.MaxValue ? 1 : 1 + minOfArgs;
 7062        }
 7063      } else if (expr is ITEExpr) {
 7064        var e = (ITEExpr)expr;
 7065        var thn = GuaranteedCoCtorsAux(e.Thn);
 7066        var els = GuaranteedCoCtorsAux(e.Els);
 7067        return thn < els ? thn : els;
 7068      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 7069        var childValues = nestedMatchExpr.Cases.Select(child => GuaranteedCoCtorsAux(child.Body)).ToList();
 7070        return childValues.Any() ? childValues.Min() : 0;
 7071      } else if (expr is MatchExpr) {
 7072        var e = (MatchExpr)expr;
 7073        var min = int.MaxValue;
 7074        foreach (var kase in e.Cases) {
 7075          var n = GuaranteedCoCtorsAux(kase.Body);
 7076          min = Math.Min(min, n);
 7077        }
 7078        return min == int.MaxValue ? 0 : min;
 7079      } else if (expr is LetExpr) {
 7080        var e = (LetExpr)expr;
 7081        return GuaranteedCoCtorsAux(e.Body);
 7082      } else if (expr is IdentifierExpr) {
 7083        var e = (IdentifierExpr)expr;
 7084        if (e.Type.IsCoDatatype && e.Var is Formal) {
 7085          // even though this is not a co-constructor, count this as 1, since that's what we would have done if it were,
 7086          return 1;
 7087        }
 7088      }
 7089      return 0;
 7090    }
 7091  }
 7092}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/TypeInferenceChecker.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.Diagnostics.Contracts;
 3using System.Linq;
 4using System.Numerics;
 5using Microsoft.Boogie;
 6using static Microsoft.Dafny.ErrorRegistry;
 7
 8namespace Microsoft.Dafny;
 9
 10partial class Resolver {
 11  class TypeInferenceCheckingContext : IASTVisitorContext {
 12    private readonly IASTVisitorContext astVisitorContext;
 13
 511014    public bool IsPrefixPredicate => astVisitorContext is PrefixPredicate;
 1169015    public bool IsExtremePredicate => astVisitorContext is ExtremePredicate;
 38338016    public bool IsPrefixDeclaration => astVisitorContext is PrefixPredicate or PrefixLemma;
 17
 4215018    public TypeInferenceCheckingContext(IASTVisitorContext astVisitorContext) {
 2107519      this.astVisitorContext = astVisitorContext;
 2107520    }
 21
 850022    ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 23  }
 24
 25  class CheckTypeInferenceVisitor : ASTVisitor<TypeInferenceCheckingContext> {
 26    private readonly Resolver resolver;
 027    private ErrorReporter reporter => resolver.reporter;
 28
 267029    public CheckTypeInferenceVisitor(Resolver resolver) {
 133530      this.resolver = resolver;
 133531    }
 32
 2107533    public override TypeInferenceCheckingContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostcon
 2107534      return new TypeInferenceCheckingContext(astVisitorContext);
 2107535    }
 36
 267037    protected override void VisitOneDeclaration(TopLevelDecl decl) {
 267038      if (decl is NewtypeDecl newtypeDecl) {
 039        if (newtypeDecl.Var != null) {
 040          if (!IsDetermined(newtypeDecl.BaseType.NormalizeExpand())) {
 041            reporter.Error(MessageSource.Resolver, newtypeDecl.tok, "newtype's base type is not fully determined; add an
 042              newtypeDecl.Var.Name);
 043          }
 044        }
 45
 356046      } else if (decl is SubsetTypeDecl subsetTypeDecl) {
 89047        if (!IsDetermined(subsetTypeDecl.Rhs.NormalizeExpand())) {
 048          reporter.Error(MessageSource.Resolver, subsetTypeDecl.tok,
 049            "subset type's base type is not fully determined; add an explicit type for '{0}'", subsetTypeDecl.Var.Name);
 050        }
 51
 267052      } else if (decl is DatatypeDecl datatypeDecl) {
 053        foreach (var member in resolver.classMembers[datatypeDecl].Values) {
 054          if (member is DatatypeDestructor dtor) {
 055            var rolemodel = dtor.CorrespondingFormals[0];
 056            for (var i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 057              var other = dtor.CorrespondingFormals[i];
 058              if (!Type.Equal_Improved(rolemodel.Type, other.Type)) {
 059                reporter.Error(MessageSource.Resolver, other,
 060                  "shared destructors must have the same type, but '{0}' has type '{1}' in constructor '{2}' and type '{
 061                  rolemodel.Name, rolemodel.Type, dtor.EnclosingCtors[0].Name, other.Type, dtor.EnclosingCtors[i].Name);
 062              }
 063            }
 064          }
 065        }
 066      }
 67
 267068      base.VisitOneDeclaration(decl);
 267069    }
 70
 44571    public override void VisitField(Field field) {
 44572      if (field is ConstantField constantField) {
 073        resolver.PartiallySolveTypeConstraints(true);
 074        CheckTypeIsDetermined(field.tok, field.Type, "const");
 075      }
 76
 44577      base.VisitField(field);
 44578    }
 79
 119732080    protected override bool VisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 119732081      if (stmt is CalcStmt calcStmt) {
 82        // The resolution of the calc statement builds up .Steps and .Result, which are of the form E0 OP E1, where
 83        // E0 and E1 are expressions from .Lines.  These additional expressions still need to have their .ResolvedOp
 84        // fields filled in, so we visit them, rather than just the parsed .Lines.
 085        Attributes.SubExpressions(calcStmt.Attributes).Iter(e => VisitExpression(e, context));
 086        calcStmt.Steps.Iter(e => VisitExpression(e, context));
 087        VisitExpression(calcStmt.Result, context);
 088        calcStmt.Hints.Iter(hint => VisitStatement(hint, context));
 089        return false; // we're done with all subcomponents of the CalcStmt
 90      }
 91
 119732092      return base.VisitOneStatement(stmt, context);
 119732093    }
 94
 119732095    protected override void PostVisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 153843096      if (stmt is VarDeclStmt) {
 34111097        var s = (VarDeclStmt)stmt;
 206397098        foreach (var local in s.Locals) {
 34688099          CheckTypeIsDetermined(local.Tok, local.Type, "local variable");
 346880100          CheckTypeArgsContainNoOrdinal(local.Tok, local.type, context);
 346880101        }
 1197320102      } else if (stmt is VarDeclPattern) {
 0103        var s = (VarDeclPattern)stmt;
 0104        s.LocalVars.Iter(local => CheckTypeIsDetermined(local.Tok, local.Type, "local variable"));
 0105        s.LocalVars.Iter(local => CheckTypeArgsContainNoOrdinal(local.Tok, local.Type, context));
 106
 856210107      } else if (stmt is ForallStmt) {
 0108        var s = (ForallStmt)stmt;
 0109        s.BoundVars.Iter(bv => CheckTypeIsDetermined(bv.tok, bv.Type, "bound variable"));
 0110        s.BoundVars.Iter(bv => CheckTypeArgsContainNoOrdinal(bv.tok, bv.Type, context));
 111
 856210112      } else if (stmt is AssignSuchThatStmt) {
 0113        var s = (AssignSuchThatStmt)stmt;
 0114        foreach (var lhs in s.Lhss) {
 0115          CheckTypeArgsContainNoOrdinal(lhs.tok, lhs.Type, context);
 0116        }
 0117      }
 118
 1197320119      base.PostVisitOneStatement(stmt, context);
 1197320120    }
 121
 2765650122    protected override void PostVisitOneExpression(Expression expr, TypeInferenceCheckingContext context) {
 3094000123      if (expr is LiteralExpr) {
 328350124        var e = (LiteralExpr)expr;
 328350125        if (e.Type.IsBitVectorType || e.Type.IsBigOrdinalType) {
 0126          var n = (BigInteger)e.Value;
 0127          var absN = n < 0 ? -n : n;
 128          // For bitvectors, check that the magnitude fits the width
 0129          if (e.Type.IsBitVectorType && MaxBV(e.Type.AsBitVectorType.Width) < absN) {
 0130            resolver.reporter.Error(MessageSource.Resolver, e.tok, "literal ({0}) is too large for the bitvector type {1
 0131          }
 132          // For bitvectors and ORDINALs, check for a unary minus that, earlier, was mistaken for a negative literal
 133          // This can happen only in `match` patterns (see comment by LitPattern.OptimisticallyDesugaredLit).
 0134          if (n < 0 || e.tok.val == "-0") {
 0135            Contract.Assert(e.tok.val == "-0");  // this and the "if" above tests that "n < 0" happens only when the tok
 0136            resolver.reporter.Error(MessageSource.Resolver, e.tok, "unary minus (-{0}, type {1}) not allowed in case pat
 0137          }
 0138        }
 139
 350400140        if (expr is StaticReceiverExpr stexpr) {
 66150141          foreach (Type t in stexpr.Type.TypeArgs) {
 0142            if (t is InferredTypeProxy && ((InferredTypeProxy)t).T == null) {
 0143              resolver.reporter.Error(MessageSource.Resolver, stexpr.tok, "type of type parameter could not be determine
 0144            }
 0145          }
 22050146        }
 147
 2770440148      } else if (expr is ComprehensionExpr) {
 4790149        var e = (ComprehensionExpr)expr;
 49440150        foreach (var bv in e.BoundVars) {
 11690151          if (!IsDetermined(bv.Type.Normalize())) {
 0152            resolver.reporter.Error(MessageSource.Resolver, bv.tok,
 0153              $"type of bound variable '{bv.Name}' could not be determined; please specify the type explicitly");
 11690154          } else if (context.IsExtremePredicate) {
 0155            CheckContainsNoOrdinal(bv.tok, bv.Type, $"type of bound variable '{bv.Name}' ('{bv.Type}') is not allowed to
 0156          }
 11690157        }
 158
 4790159        if (e is ExistsExpr && e.Range == null) {
 0160          var binBody = ((ExistsExpr)e).Term as BinaryExpr;
 0161          if (binBody != null && binBody.Op == BinaryExpr.Opcode.Imp) {  // check Op, not ResolvedOp, in order to distin
 162                                                                         // apply the wisdom of Claude Marche: issue a w
 0163            resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0164              "the quantifier has the form 'exists x :: A ==> B', which most often is a typo for 'exists x :: A && B'; "
 0165              "if you think otherwise, rewrite as 'exists x :: (A ==> B)' or 'exists x :: !A || B' to suppress this warn
 0166          }
 0167        }
 168
 2460590169      } else if (expr is MemberSelectExpr) {
 23290170        var e = (MemberSelectExpr)expr;
 37170171        if (e.Member is Function || e.Member is Method) {
 13880172          var i = 0;
 41640173          foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustMember)) {
 0174            var tp = i < e.TypeApplication_AtEnclosingClass.Count
 0175              ? e.Member.EnclosingClass.TypeArgs[i]
 0176              : ((ICallable)e.Member).TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 0177            if (!IsDetermined(p.Normalize())) {
 0178              resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0179                $"type parameter '{tp.Name}' (inferred to be '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' could n
 0180            } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat i
 0181              CheckContainsNoOrdinal(e.tok, p,
 0182                $"type parameter '{tp.Name}' (passed in as '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' is not al
 0183            }
 0184            i++;
 0185          }
 13880186        }
 2440680187      } else if (expr is FunctionCallExpr) {
 8170188        var e = (FunctionCallExpr)expr;
 8170189        var i = 0;
 39840190        foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustFunction)) {
 5110191          var tp = i < e.TypeApplication_AtEnclosingClass.Count
 5110192            ? e.Function.EnclosingClass.TypeArgs[i]
 5110193            : e.Function.TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 5110194          if (!IsDetermined(p.Normalize())) {
 0195            var hint = e.Name.StartsWith("reveal_")
 0196              ? ". If you are making an opaque function, make sure that the function can be called."
 0197              : "";
 0198            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0199              $"type parameter '{tp.Name}' (inferred to be '{p}') in the function call to '{e.Name}' could not be determ
 10220200          } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat it 
 5110201            CheckContainsNoOrdinal(e.tok, p,
 5110202              $"type parameter '{tp.Name}' (passed in as '{p}') to function call '{e.Name}' is not allowed to use ORDINA
 5110203          }
 5110204          i++;
 5110205        }
 2445720206      } else if (expr is LetExpr) {
 36500207        var e = (LetExpr)expr;
 219000208        foreach (var p in e.LHSs) {
 219000209          foreach (var x in p.Vars) {
 36500210            if (!IsDetermined(x.Type.Normalize())) {
 0211              resolver.reporter.Error(MessageSource.Resolver, x.tok, $"the type of the bound variable '{x.Name}' could n
 36500212            } else {
 36500213              CheckTypeArgsContainNoOrdinal(x.tok, x.Type, context);
 36500214            }
 36500215          }
 36500216        }
 3530660217      } else if (expr is IdentifierExpr) {
 218        // by specializing for IdentifierExpr, error messages will be clearer
 1129610219        CheckTypeIsDetermined(expr.tok, expr.Type, "variable");
 2365510220      } else if (expr is ConversionExpr) {
 960221        var e = (ConversionExpr)expr;
 960222        if (e.ToType.IsRefType) {
 0223          var fromType = e.E.Type;
 0224          Contract.Assert(fromType.IsRefType);
 0225          if (fromType.IsSubtypeOf(e.ToType, false, true) || e.ToType.IsSubtypeOf(fromType, false, true)) {
 226            // looks good
 0227          } else {
 0228            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0229              "a type cast to a reference type ({0}) must be from a compatible type (got {1}); this cast could never suc
 0230              e.ToType, fromType);
 0231          }
 0232        }
 1234940233      } else if (expr is TypeTestExpr) {
 0234        var e = (TypeTestExpr)expr;
 0235        var fromType = e.E.Type;
 0236        if (fromType.IsSubtypeOf(e.ToType, false, true)) {
 237          // This test is allowed and it always returns true
 0238        } else if (!e.ToType.IsSubtypeOf(fromType, false, true)) {
 0239          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0240            "a type test to '{0}' must be from a compatible type (got '{1}')", e.ToType, fromType);
 0241        } else if (!e.ToType.IsRefType) {
 0242          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0243            "a non-trivial type test is allowed only for reference types (tried to test if '{1}' is a '{0}')", e.ToType,
 0244        }
 2467960245      } else if (CheckTypeIsDetermined(expr.tok, expr.Type, "expression")) {
 1243760246        if (expr is UnaryOpExpr uop) {
 247          // The CheckTypeInference_Visitor has already visited uop.E, but uop.E's may be undetermined. If that happened
 248          // then an error has already been reported.
 19560249          if (CheckTypeIsDetermined(uop.E.tok, uop.E.Type, "expression")) {
 9780250            uop.ResolveOp(); // Force resolution eagerly at this point to catch potential bugs
 9780251          }
 1301590252        } else if (expr is BinaryExpr) {
 67610253          var e = (BinaryExpr)expr;
 67610254          e.ResolvedOp = ResolveOp(e.Op, e.E0.Type, e.E1.Type);
 255          // Check for useless comparisons with "null"
 67610256          Expression other = null;  // if "null" if one of the operands, then "other" is the other
 67610257          if (e.E0 is LiteralExpr && ((LiteralExpr)e.E0).Value == null) {
 0258            other = e.E1;
 68500259          } else if (e.E1 is LiteralExpr && ((LiteralExpr)e.E1).Value == null) {
 890260            other = e.E0;
 890261          }
 68500262          if (other != null) {
 890263            bool sense = true;
 890264            switch (e.ResolvedOp) {
 265              case BinaryExpr.ResolvedOpcode.NeqCommon:
 890266                sense = false;
 890267                goto case BinaryExpr.ResolvedOpcode.EqCommon;
 890268              case BinaryExpr.ResolvedOpcode.EqCommon: {
 890269                  var nntUdf = other.Type.AsNonNullRefType;
 890270                  if (nntUdf != null) {
 0271                    string name = null;
 0272                    string hint = "";
 0273                    other = other.Resolved;
 0274                    if (other is IdentifierExpr) {
 0275                      name = $"variable '{((IdentifierExpr)other).Name}'";
 0276                    } else if (other is MemberSelectExpr) {
 0277                      var field = ((MemberSelectExpr)other).Member as Field;
 278                      // The type of the field may be a formal type parameter, in which case the hint is omitted
 0279                      if (field.Type.IsNonNullRefType) {
 0280                        name = $"field '{field.Name}'";
 0281                      }
 0282                    }
 0283                    if (name != null) {
 284                      // The following relies on that a NonNullTypeDecl has a .Rhs that is a
 285                      // UserDefinedType denoting the possibly null type declaration and that
 286                      // these two types have the same number of type arguments.
 0287                      var nonNullTypeDecl = (NonNullTypeDecl)nntUdf.ResolvedClass;
 0288                      var possiblyNullUdf = (UserDefinedType)nonNullTypeDecl.Rhs;
 0289                      var possiblyNullTypeDecl = (ClassDecl)possiblyNullUdf.ResolvedClass;
 0290                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == possiblyNullTypeDecl.TypeArgs.Count);
 0291                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == nntUdf.TypeArgs.Count);
 0292                      var ty = new UserDefinedType(nntUdf.tok, possiblyNullUdf.Name, possiblyNullTypeDecl, nntUdf.TypeAr
 293
 0294                      hint = $" (to make it possible for {name} to have the value 'null', declare its type to be '{ty}')
 0295                    }
 0296                    var b = sense ? "false" : "true";
 0297                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0298                      $"the type of the other operand is a non-null type, so this comparison with 'null' will always ret
 0299                  }
 890300                  break;
 301                }
 302              case BinaryExpr.ResolvedOpcode.NotInSet:
 303              case BinaryExpr.ResolvedOpcode.NotInSeq:
 304              case BinaryExpr.ResolvedOpcode.NotInMultiSet:
 0305                sense = false;
 0306                goto case BinaryExpr.ResolvedOpcode.InSet;
 307              case BinaryExpr.ResolvedOpcode.InSet:
 308              case BinaryExpr.ResolvedOpcode.InSeq:
 0309              case BinaryExpr.ResolvedOpcode.InMultiSet: {
 0310                  var ty = other.Type.NormalizeExpand();
 0311                  var what = ty is SetType ? "set" : ty is SeqType ? "seq" : "multiset";
 0312                  if (((CollectionType)ty).Arg.IsNonNullRefType) {
 0313                    var non = sense ? "" : "non-";
 0314                    var b = sense ? "false" : "true";
 0315                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0316                      $"the type of the other operand is a {what} of non-null elements, so the {non}inclusion test of 'n
 0317                  }
 0318                  break;
 319                }
 320              case BinaryExpr.ResolvedOpcode.NotInMap:
 0321                goto case BinaryExpr.ResolvedOpcode.InMap;
 0322              case BinaryExpr.ResolvedOpcode.InMap: {
 0323                  var ty = other.Type.NormalizeExpand();
 0324                  if (((MapType)ty).Domain.IsNonNullRefType) {
 0325                    var b = sense ? "false" : "true";
 0326                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0327                      $"the type of the other operand is a map to a non-null type, so the inclusion test of 'null' will 
 0328                  }
 0329                  break;
 330                }
 331              default:
 0332                break;
 333            }
 890334          }
 1261020335        } else if (expr is NegationExpression) {
 36820336          var e = (NegationExpression)expr;
 36820337          Expression resolved = null;
 72750338          if (e.E is LiteralExpr lit) { // note, not e.E.Resolved, since we don't want to do this for double negations
 339                                        // For real-based types, integer-based types, and bi (but not bitvectors), "-" f
 340                                        // just a literal expression with a negative value
 35930341            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 0342              var d = (BaseTypes.BigDec)lit.Value;
 0343              Contract.Assert(!d.IsNegative);
 0344              resolved = new LiteralExpr(e.tok, -d);
 71860345            } else if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 35930346              var n = (BigInteger)lit.Value;
 35930347              Contract.Assert(0 <= n);
 35930348              resolved = new LiteralExpr(e.tok, -n);
 35930349            }
 35930350          }
 37710351          if (resolved == null) {
 352            // Treat all other expressions "-e" as "0 - e"
 353            Expression zero;
 890354            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 0355              zero = new LiteralExpr(e.tok, BaseTypes.BigDec.ZERO);
 890356            } else {
 890357              Contract.Assert(e.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || e.E.Type.IsBitVectorType);
 890358              zero = new LiteralExpr(e.tok, 0);
 890359            }
 890360            zero.Type = expr.Type;
 890361            resolved = new BinaryExpr(e.tok, BinaryExpr.Opcode.Sub, zero, e.E) { ResolvedOp = BinaryExpr.ResolvedOpcode.
 890362          }
 36820363          resolved.Type = expr.Type;
 36820364          e.ResolvedExpression = resolved;
 36820365        }
 1233980366      }
 367
 2765650368      base.PostVisitOneExpression(expr, context);
 2765650369    }
 370
 0371    protected override void VisitExtendedPattern(ExtendedPattern pattern, TypeInferenceCheckingContext context) {
 0372      base.VisitExtendedPattern(pattern, context);
 373
 0374      if (pattern is IdPattern { BoundVar: { } bv }) {
 0375        CheckTypeIsDetermined(bv.Tok, bv.Type, "bound variable");
 0376      }
 0377    }
 378
 556044485379    public static bool IsDetermined(Type t) {
 380      Contract.Requires(t != null);
 381      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);
 382      // all other proxies indicate the type has not yet been determined, provided their type parameters have been
 561454380383      return !(t is TypeProxy) && t.TypeArgs.All(tt => IsDetermined(tt.Normalize()));
 556044485384    }
 385
 1335386    readonly ISet<TypeProxy> UnderspecifiedTypeProxies = new HashSet<TypeProxy>();
 387
 7053395388    public bool CheckTypeIsDetermined(IToken tok, Type t, string what) {
 389      Contract.Requires(tok != null);
 390      Contract.Requires(t != null);
 391      Contract.Requires(what != null);
 7053395392      t = t.NormalizeExpandKeepConstraints();
 393
 7053395394      if (t is TypeProxy) {
 0395        var proxy = (TypeProxy)t;
 0396        if (!UnderspecifiedTypeProxies.Contains(proxy)) {
 397          // report an error for this TypeProxy only once
 0398          resolver.reporter.Error(MessageSource.Resolver, tok, "the type of this {0} is underspecified", what);
 0399          UnderspecifiedTypeProxies.Add(proxy);
 0400        }
 0401        return false;
 402      }
 403      // Recurse on type arguments:
 11386540404      return t.TypeArgs.All(rg => CheckTypeIsDetermined(tok, rg, what));
 7053395405    }
 406
 383380407    public void CheckTypeArgsContainNoOrdinal(IToken tok, Type t, TypeInferenceCheckingContext context) {
 408      Contract.Requires(tok != null);
 409      Contract.Requires(t != null);
 383380410      if (context.IsPrefixDeclaration) {
 411        // User-provided expressions in extreme predicates/lemmas are checked in the extreme declarations, so need
 412        // need to do them here again for the prefix predicates/lemmas.
 383380413      } else {
 383380414        t = t.NormalizeExpand();
 719010415        t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, "an ORDINAL type is not allowed to be used as a type argum
 383380416      }
 383380417    }
 418
 677970419    public void CheckContainsNoOrdinal(IToken tok, Type t, string errMsg) {
 420      Contract.Requires(tok != null);
 421      Contract.Requires(t != null);
 422      Contract.Requires(errMsg != null);
 677970423      t = t.NormalizeExpand();
 677970424      if (t.IsBigOrdinalType) {
 0425        resolver.reporter.Error(MessageSource.Resolver, tok, errMsg);
 0426      }
 1015200427      t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, errMsg));
 677970428    }
 429  }
 430}

Methods/Properties

get_AllowedToDependOnAllocationState()
get_Kind()
.ctor(Microsoft.Dafny.IASTVisitorContext)
.ctor(Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext,Microsoft.Dafny.LambdaExpr)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
.ctor(Microsoft.Dafny.ErrorReporter)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitTopLevelFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DesugarFunctionsInFrameClause(Microsoft.Dafny.FrameExpression)
FrameArrowToObjectSet(Microsoft.Dafny.Expression)
VisitExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DiscoverBestBounds_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverBestBounds_MultipleVars_AllowReordering(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_Aux_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_SingleVar(VT,Microsoft.Dafny.Expression)
DiscoverAllBounds_Aux_SingleVar(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
DiscoverBoundsFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,VT,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
NormalizedConjuncts()
SanitizeForBoundDiscovery(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.BinaryExpr/ResolvedOpcode,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
IsMonotonic(Microsoft.Dafny.Expression,Microsoft.Dafny.IVariable,System.Boolean)
ResolveNamesAndInferTypes(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,System.Boolean)
ResolveNamesAndInferTypesForOneDeclarationInitial(Microsoft.Dafny.TopLevelDecl)
ResolveNamesAndInferTypesForOneDeclaration(Microsoft.Dafny.TopLevelDecl)
EagerAddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression,System.String)
PrintTypeConstraintState(System.Int32)
SolveAllTypeConstraints()
ResolveAttributes(Microsoft.Dafny.IAttributeBearingDeclaration,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveTypeParameters(System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean,Microsoft.Dafny.TypeParameter/ParentType)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,System.String,System.Object[])
ConstrainTypeExprBool(Microsoft.Dafny.Expression,System.String)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.IToken,System.String,System.Object[])
ConstrainAssignable(Microsoft.Dafny.NonProxyType,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&,System.Boolean)
ConstrainAssignableTypeArgs(Microsoft.Dafny.Type,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&)
ConstrainSubtypeRelation_Equal(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean,System.Boolean)
ConstrainSubtypeRelation_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint,System.Boolean,System.Boolean)
DetermineRootLeaf(Microsoft.Dafny.Type,System.Boolean&,System.Boolean&,System.Boolean&,System.Boolean&)
.ctor(Microsoft.Dafny.DafnyOptions)
AssignProxyAndHandleItsConstraints(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
AssignProxyAndHandleItsConstraints_aux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
ImposeSubtypingConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainTypeHead_Recursive(Microsoft.Dafny.Type,Microsoft.Dafny.Type&)
ConstrainTypeHead(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
KeepConstraints(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
ToString()
Confirm(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean&,System.Boolean&)
ProxyWithNoSubTypeConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Resolver)
CouldBeAnything()
FindCollectionType(Microsoft.Dafny.DafnyOptions,Microsoft.Dafny.Type,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.Expression[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
PartiallySolveTypeConstraints(System.Boolean)
NewIntegerBasedProxy(Microsoft.Dafny.IToken)
ContainsAsTypeParameter(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
AddAllProxies(Microsoft.Dafny.Type,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ProcessAssignable(Microsoft.Dafny.TypeProxy,System.Collections.Generic.List`1<Microsoft.Dafny.Type>)
ConvertAssignableToSubtypeConstraints(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
TightenUpEquatable(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ProcessOneSubtypingConstraintAndItsSubs(Microsoft.Dafny.TypeConstraint,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeConstraint>,System.Boolean,System.Boolean&)
ProcessFullStrength_SubDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
ProcessFullStrength_SuperDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
AssignKnownEnd(Microsoft.Dafny.TypeProxy,System.Boolean,System.Boolean)
AssignKnownEndsFullstrength(Microsoft.Dafny.TypeProxy)
AssignKnownEndsFullstrength_SubDirection(Microsoft.Dafny.TypeProxy)
CloseOverAssignableRhss(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint_SubDirection(Microsoft.Dafny.TypeProxy)
HasApplicableNullableRefTypeConstraint_SubDirection_aux(Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
AssignKnownEndsFullstrength_SuperDirection(Microsoft.Dafny.TypeProxy)
Reaches(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
Reaches_aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ResolveClassMemberBodiesInitial(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberBodies(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveCtorTypes(Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
ResolveCtorSignature(Microsoft.Dafny.DatatypeCtor,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
AddDatatypeDependencyEdge(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Type,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ResolveFrameExpressionTopLevel(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ICodeContext)
ResolveFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ResolutionContext)
ResolveIterator(Microsoft.Dafny.IteratorDecl)
CheckIsLvalue(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveBlockStatement(Microsoft.Dafny.BlockStmt,Microsoft.Dafny.ResolutionContext)
ResolveStatementWithLabels(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveAlternatives(System.Collections.Generic.List`1<Microsoft.Dafny.GuardedAlternative>,Microsoft.Dafny.AlternativeLoopStmt,Microsoft.Dafny.ResolutionContext)
ResolveCallStmt(Microsoft.Dafny.CallStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Type)
ResolveActualParameters(Microsoft.Dafny.ActualBindings,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.IToken,System.Object,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Expression)
GetLocationInformation(Microsoft.Dafny.Formal,System.Int32,System.Int32,System.String)
ResolveDotSuffix_Type(Microsoft.Dafny.ExprDotName,Microsoft.Dafny.ResolutionContext,System.Boolean,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CreateResolver_IdentifierExpr(Microsoft.Dafny.IToken,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TopLevelDecl)
ResolveStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveLoopSpecificationComponents(System.Collections.Generic.List`1<Microsoft.Dafny.AttributedExpression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.FrameExpression>,Microsoft.Dafny.ResolutionContext)
ResolveParameterDefaultValues(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ResolutionContext)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.ExprDotName)
ResolveTypeLenient(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean)
FillInTypeArguments(Microsoft.Dafny.IToken,System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,Microsoft.Dafny.Resolver/ResolveTypeOption)
TypeConstraintsIncludeProxy(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy)
TypeConstraintsIncludeProxy_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ResolveTypeRhs(Microsoft.Dafny.TypeRhs,Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveMember(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,Microsoft.Dafny.NonProxyType&)
PartiallyResolveTypeForMemberSelection(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,System.Int32)
GetBaseTypeFromProxy(Microsoft.Dafny.TypeProxy,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_Eq(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_EqAux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetRelatedTypeProxies(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
JoinOfAllSubtypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
MeetOfAllSupertypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean)
CheckVariance(Microsoft.Dafny.Type,Microsoft.Dafny.ICallable,Microsoft.Dafny.TypeParameter/TPVariance,System.Boolean)
ConstrainToIntegerType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ResolveDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<System.Tuple`3<Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.List`1<Microsoft.Dafny.MemberDecl>&,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>&)
DesugarDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>,System.Collections.Generic.Dictionary`2<System.String,System.Tuple`3<Microsoft.Dafny.BoundVar,Microsoft.Dafny.IdentifierExpr,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean,Microsoft.Dafny.ModuleDecl&)
ResolveDatatypeConstructor(Microsoft.Dafny.NameSegment,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Tuple`2<Microsoft.Dafny.DatatypeCtor,System.Boolean>,System.String,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
ResolveNameSegment_Type(Microsoft.Dafny.NameSegment,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveDotSuffix(Microsoft.Dafny.ExprDotName,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean)
CheckForAmbiguityInShadowedImportedModule(Microsoft.Dafny.ModuleDecl,System.String,Microsoft.Dafny.IToken,System.Boolean,System.Boolean)
NameConflictsWithModuleContents(Microsoft.Dafny.ModuleDecl,System.String,System.Boolean,System.Boolean)
ResolveExprDotCall(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.Type,Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveApplySuffix(Microsoft.Dafny.ApplySuffix,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveDatatypeValue(Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.DatatypeValue,Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Type,System.Boolean)
ResolveFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,Microsoft.Dafny.ResolutionContext)
ResolveReceiver(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveSeqSelectExpr(Microsoft.Dafny.SeqSelectExpr,Microsoft.Dafny.ResolutionContext)
get_Options()
.ctor(Microsoft.Dafny.DafnyOptions)
get_Reporter()
get_TypeConstraintErrorsToBeReported()
RevealedInScope(Microsoft.Dafny.Declaration)
VisibleInScope(Microsoft.Dafny.Declaration)
FreshTempVarName(System.String,Microsoft.Dafny.ICodeContext)
Create(Microsoft.Dafny.ModuleDefinition,Thing,Thing,System.Collections.Generic.IEqualityComparer`1<Thing>,System.Collections.Generic.ISet`1<Thing>&)
Name(System.Collections.Generic.ISet`1<Thing>,System.Func`2<Thing,System.String>)
ModuleNames(Microsoft.Dafny.Resolver/IAmbiguousThing`1<Thing>,System.Func`2<Thing,System.String>)
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
Equals(Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
GetHashCode(Microsoft.Dafny.TopLevelDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.TopLevelDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()
ModuleNames()
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
Equals(Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
GetHashCode(Microsoft.Dafny.MemberDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()
ModuleNames()
.ctor(Microsoft.Dafny.Program)
AddRotateMember(Microsoft.Dafny.ValuetypeDecl,System.String,Microsoft.Dafny.Type)
ObjectInvariant()
AsValuetypeDecl(Microsoft.Dafny.Type)
CheckDupModuleNames(Microsoft.Dafny.Program)
ResolveProgram(Microsoft.Dafny.Program)
ResolveValuetypeDecls()
ResolveModuleDefinition(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Boolean)
ResolveModuleExport(Microsoft.Dafny.LiteralModuleDecl,Microsoft.Dafny.ModuleSignature)
CheckModuleExportConsistency(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver/ModuleBindings)
BindName(System.String,Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings)
TryLookup(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&)
TryLookupFilter(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&,System.Func`2<Microsoft.Dafny.ModuleDecl,System.Boolean>)
get_ModuleList()
SubBindings(System.String)
BindModuleNames(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings)
ShortenPrefix(System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>)
BindModuleName_LiteralModuleDecl(Microsoft.Dafny.LiteralModuleDecl,System.Collections.Generic.List`1<System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>>,Microsoft.Dafny.Resolver/ModuleBindings)
ResolveQualifiedModuleIdRootRefines(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootImport(Microsoft.Dafny.AliasModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootAbstract(Microsoft.Dafny.AbstractModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ProcessDependenciesDefinition(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ProcessDependencies(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ModuleNotFoundErrorMessage(System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Name>,System.String)
EquivIfPresent(System.Collections.Generic.Dictionary`2<T1,T2>,T1,T2)
MergeSignature(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleSignature)
ResolveOpenedImports(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,System.Boolean,Microsoft.Dafny.Resolver)
ResolveAlias(Microsoft.Dafny.TopLevelDecl)
ResolveOpenedImportsWorker(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDecl,System.Collections.Generic.HashSet`1<Microsoft.Dafny.ModuleSignature>,System.Boolean,Microsoft.Dafny.TopLevelDecl&)
RegisterTopLevelDecls(Microsoft.Dafny.ModuleDefinition,System.Boolean)
RegisterMembers(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDeclWithMembers,System.Collections.Generic.Dictionary`2<System.String,Microsoft.Dafny.MemberDecl>)
RegisterByMethod(Microsoft.Dafny.Function,Microsoft.Dafny.TopLevelDeclWithMembers)
MakeAbstractSignature(Microsoft.Dafny.ModuleSignature,System.String,System.Int32,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
CloneDeclaration(Microsoft.Dafny.VisibilityScope,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.ModuleDefinition,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
ResolveModuleQualifiedId(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ErrorReporter)
ResolveExport(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleQualifiedId,System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.ModuleSignature&,Microsoft.Dafny.ErrorReporter)
RevealAllInScope(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.VisibilityScope)
ResolveTopLevelDecls_Signatures(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
.cctor()
ResolveTopLevelDecls_Core(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>,System.String,System.Boolean)
FillInPostConditionsAndBodiesOfPrefixLemmas(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>)
CheckIsOkayWithoutRHS(Microsoft.Dafny.ConstantField)
ResolveClassMembers_Pass1(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckForUnnecessaryEqualitySupportDeclarations(Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CheckParameterDefaultValuesAreCompilable(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ICodeContext)
ReportCallGraphCycleError(Microsoft.Dafny.ICallable,System.String)
ReportCycleError(System.Collections.Generic.List`1<X>,System.Func`2<X,Microsoft.Dafny.IToken>,System.Func`2<X,System.String>,System.String)
MaxBV(Microsoft.Dafny.Type)
MaxBV(System.Int32)
FigureOutNativeType(Microsoft.Dafny.NewtypeDecl)
CheckOlderParameters(Microsoft.Dafny.Function)
CheckExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
CheckExpression(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
VisitOneExpr(Microsoft.Dafny.Expression)
VisitOneStmt(Microsoft.Dafny.Statement)
CheckForFuelAdjustments(Microsoft.Dafny.IToken,Microsoft.Dafny.Attributes,Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/FuelAdjustment_Context&)
Invert(Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
KNatMismatchError(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.ExtremePredicate/KType,Microsoft.Dafny.ExtremePredicate/KType)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremePredicate)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/CallingPosition&)
ExtremePredicateChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremePredicate,Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremeLemma)
VisitOneStmt(Microsoft.Dafny.Statement)
VisitOneExpr(Microsoft.Dafny.Expression)
ExtremeLemmaChecks(Microsoft.Dafny.Statement,Microsoft.Dafny.ExtremeLemma)
ExtremeLemmaChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremeLemma)
CheckTypeCharacteristics_Stmt(Microsoft.Dafny.Statement,System.Boolean)
CheckTypeCharacteristics_Expr(Microsoft.Dafny.Expression,System.Boolean)
CheckTypeCharacteristics_Type(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,System.Boolean&)
VisitOneExpr(Microsoft.Dafny.Expression,System.Boolean&)
VisitType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
CheckTypeInstantiation(Microsoft.Dafny.IToken,System.String,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Boolean)
CheckCharacteristics(Microsoft.Dafny.TypeParameter/TypeParameterCharacteristics,Microsoft.Dafny.Type,System.Boolean,System.String&,System.String&)
TypeEqualityErrorMessageHint(Microsoft.Dafny.Type)
CanCompareWith(Microsoft.Dafny.Expression)
ComputeGhostInterest(Microsoft.Dafny.Statement,System.Boolean,System.String,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICallable)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
CheckInit(System.Collections.Generic.List`1<Microsoft.Dafny.Statement>)
CheckInit(Microsoft.Dafny.Statement)
VisitExpr(Microsoft.Dafny.Expression)
VisitOneExpr(Microsoft.Dafny.Expression,System.Int32&)
LiberalRHSVisit(Microsoft.Dafny.Expression)
IsThisDotField(Microsoft.Dafny.MemberSelectExpr)
IsCollectionOperator(Microsoft.Dafny.BinaryExpr/ResolvedOpcode)
InferRequiredEqualitySupport(Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type)
ResolveParentTraitTypes(Microsoft.Dafny.TopLevelDeclWithMembers,Microsoft.Dafny.Graph`1<Microsoft.Dafny.TopLevelDeclWithMembers>)
RegisterInheritedMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberTypes(Microsoft.Dafny.TopLevelDeclWithMembers)
InheritedTraitMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckOverride_FunctionParameters(Microsoft.Dafny.Function,Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_MethodParameters(Microsoft.Dafny.Method,Microsoft.Dafny.Method,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_TypeParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_ResolvedParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.String,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
SccStratosphereCheck(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ComputeGroundingCtor(Microsoft.Dafny.IndDatatypeDecl)
CheckCanBeConstructed(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeParameter>)
DetermineEqualitySupport(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
IsRecognizedAttribute(Microsoft.Dafny.UserSuppliedAttributes,Microsoft.Dafny.IAttributeBearingDeclaration)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Microsoft.Dafny.IVariable>,Microsoft.Dafny.IVariable,System.String)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Thing>,System.String,Thing,Microsoft.Dafny.IToken,System.String)
ResolveFunctionSignature(Microsoft.Dafny.Function)
DisallowNonGhostFieldSpecifiers(Microsoft.Dafny.FrameExpression)
ResolveMethodSignature(Microsoft.Dafny.Method)
ResolveIteratorSignature(Microsoft.Dafny.IteratorDecl)
ObjectInvariant()
.ctor(Microsoft.Dafny.ResolveTypeOptionEnum)
.ctor(Microsoft.Dafny.TypeParameter/ParentType)
ResolvedArrayType(Microsoft.Dafny.IToken,System.Int32,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,System.Boolean)
FillInDefaultLoopDecreases(Microsoft.Dafny.LoopStmt,Microsoft.Dafny.Expression,System.Collections.Generic.List`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.ICallable)
VarDotMethod(Microsoft.Dafny.IToken,System.String,System.String)
makeTemp(System.String,Microsoft.Dafny.AssignOrReturnStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Expression)
EnsureSupportsErrorHandling(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,System.Boolean)
CheckLocalityUpdates(Microsoft.Dafny.Statement,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
CheckLocalityUpdatesLhs(Microsoft.Dafny.Expression,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
ToString()
FindAllMembers(Microsoft.Dafny.ClassDecl,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
GetThisType(Microsoft.Dafny.IToken,Microsoft.Dafny.TopLevelDeclWithMembers)
GetReceiverType(Microsoft.Dafny.IToken,Microsoft.Dafny.MemberDecl)
ResolveDominatingLabelInExpr(Microsoft.Dafny.IToken,System.String,System.String,Microsoft.Dafny.ResolutionContext)
VarDotFunction(Microsoft.Dafny.IToken,System.String,System.String)
LetPatIn(Microsoft.Dafny.IToken,Microsoft.Dafny.CasePattern`1<Microsoft.Dafny.BoundVar>,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
LetVarIn(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
ResolveLetOrFailExpr(Microsoft.Dafny.LetOrFailExpr,Microsoft.Dafny.ResolutionContext)
SelectAppropriateArrowTypeForFunction(Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.BuiltIns)
SelectAppropriateArrowType(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.BuiltIns)
ConstrainToIntegerType(Microsoft.Dafny.Expression,System.Boolean,System.String)
ResolveNestedMatchExpr(Microsoft.Dafny.NestedMatchExpr,Microsoft.Dafny.ResolutionContext)
ResolveCasePattern(Microsoft.Dafny.CasePattern`1<VT>,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext)
FillInDefaultValueExpressions()
FillInDefaultValueExpression(Microsoft.Dafny.DefaultValueExpression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>,Microsoft.Dafny.Expression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.IVariable,Microsoft.Dafny.Expression>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
Substitute(Microsoft.Dafny.Expression)
BuildTypeArgumentSubstitute(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
AddParentTypeParameterSubstitutions(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
GhostPrefix(System.Boolean)
GetSignatureExt(Microsoft.Dafny.ModuleSignature,System.Boolean)
GetSignature(Microsoft.Dafny.ModuleSignature)
GetImpliedTypeConstraint(Microsoft.Dafny.IVariable,Microsoft.Dafny.Type)
GetImpliedTypeConstraint(Microsoft.Dafny.Expression,Microsoft.Dafny.Type)
FreeVariables(Microsoft.Dafny.Expression)
.cctor()
get_Msg()
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
ResolveOp(Microsoft.Dafny.BinaryExpr/Opcode,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
CollectFriendlyCallsInExtremeLemmaSpecification(Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
get_IsPrefixPredicate()
get_IsExtremePredicate()
get_IsPrefixDeclaration()
.ctor(Microsoft.Dafny.IASTVisitorContext)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
get_reporter()
.ctor(Microsoft.Dafny.Resolver)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneDeclaration(Microsoft.Dafny.TopLevelDecl)
VisitField(Microsoft.Dafny.Field)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
VisitExtendedPattern(Microsoft.Dafny.ExtendedPattern,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
IsDetermined(Microsoft.Dafny.Type)
CheckTypeIsDetermined(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)
CheckTypeArgsContainNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
CheckContainsNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)